Merge "DO NOT MERGE ANYWHERE Add AOSP Geomag and Game Rotation, and Gravity" into cw-e-dev am: dd9012bf09  -s ours
am: d2ebf37473  -s ours

* commit 'd2ebf374732d6824fffc69fcffe9395b5a4a842c':
  DO NOT MERGE ANYWHERE Add AOSP Geomag and Game Rotation, and Gravity

Change-Id: I43a30806ab719a017e9966570ba74725137c1cdd
diff --git a/aidl/binder/android/os/PersistableBundle.aidl b/aidl/binder/android/os/PersistableBundle.aidl
new file mode 100644
index 0000000..94e8607
--- /dev/null
+++ b/aidl/binder/android/os/PersistableBundle.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2014, The Android Open Source Project
+**
+** 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.
+*/
+
+package android.os;
+
+parcelable PersistableBundle cpp_header "binder/PersistableBundle.h";
diff --git a/aidl/gui/android/view/Surface.aidl b/aidl/gui/android/view/Surface.aidl
new file mode 100644
index 0000000..674c163
--- /dev/null
+++ b/aidl/gui/android/view/Surface.aidl
@@ -0,0 +1,20 @@
+/* //device/java/android/android/view/Surface.aidl
+**
+** Copyright 2007, The Android Open Source Project
+**
+** 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.
+*/
+
+package android.view;
+
+parcelable Surface cpp_header "gui/Surface.h";
diff --git a/cmds/atrace/Android.mk b/cmds/atrace/Android.mk
index 028ca8f..a787e95 100644
--- a/cmds/atrace/Android.mk
+++ b/cmds/atrace/Android.mk
@@ -17,4 +17,6 @@
     libutils \
     libz \
 
+LOCAL_INIT_RC := atrace.rc
+
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 55282cf..facf300 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+ #define LOG_TAG "atrace"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
@@ -26,6 +28,7 @@
 #include <string.h>
 #include <sys/sendfile.h>
 #include <time.h>
+#include <unistd.h>
 #include <zlib.h>
 
 #include <binder/IBinder.h>
@@ -36,16 +39,22 @@
 
 #include <utils/String8.h>
 #include <utils/Timers.h>
+#include <utils/Tokenizer.h>
 #include <utils/Trace.h>
 
 using namespace android;
 
 #define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
 
-enum { MAX_SYS_FILES = 10 };
+#define MAX_SYS_FILES 10
+#define MAX_PACKAGES 16
 
 const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
-const char* k_traceAppCmdlineProperty = "debug.atrace.app_cmdlines";
+
+const char* k_traceAppsNumberProperty = "debug.atrace.app_number";
+const char* k_traceAppsPropertyTemplate = "debug.atrace.app_%d";
+const char* k_coreServiceCategory = "core_services";
+const char* k_coreServicesProp = "ro.atrace.core.services";
 
 typedef enum { OPT, REQ } requiredness  ;
 
@@ -90,17 +99,24 @@
     { "rs",         "RenderScript",     ATRACE_TAG_RS, { } },
     { "bionic",     "Bionic C Library", ATRACE_TAG_BIONIC, { } },
     { "power",      "Power Management", ATRACE_TAG_POWER, { } },
+    { "pm",         "Package Manager",  ATRACE_TAG_PACKAGE_MANAGER, { } },
+    { "ss",         "System Server",    ATRACE_TAG_SYSTEM_SERVER, { } },
+    { "database",   "Database",         ATRACE_TAG_DATABASE, { } },
+    { k_coreServiceCategory, "Core services", 0, { } },
     { "sched",      "CPU Scheduling",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
         { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable" },
     } },
     { "irq",        "IRQ Events",   0, {
         { REQ,      "/sys/kernel/debug/tracing/events/irq/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/ipi/enable" },
     } },
     { "freq",       "CPU Frequency",    0, {
         { REQ,      "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" },
         { OPT,      "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" },
+        { OPT,      "/sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable" },
     } },
     { "membus",     "Memory Bus Utilization", 0, {
         { REQ,      "/sys/kernel/debug/tracing/events/memory_bus/enable" },
@@ -150,6 +166,9 @@
         { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_locked/enable" },
         { REQ,      "/sys/kernel/debug/tracing/events/binder/binder_unlock/enable" },
     } },
+    { "pagecache",  "Page cache", 0, {
+        { REQ,      "/sys/kernel/debug/tracing/events/filemap/enable" },
+    } },
 };
 
 /* Command line options */
@@ -159,8 +178,10 @@
 static bool g_compress = false;
 static bool g_nohup = false;
 static int g_initialSleepSecs = 0;
+static const char* g_categoriesFile = NULL;
 static const char* g_kernelTraceFuncs = NULL;
 static const char* g_debugAppCmdLine = "";
+static const char* g_outputFile = nullptr;
 
 /* Global state */
 static bool g_traceAborted = false;
@@ -206,6 +227,9 @@
 static const char* k_tracePath =
     "/sys/kernel/debug/tracing/trace";
 
+static const char* k_traceStreamPath =
+    "/sys/kernel/debug/tracing/trace_pipe";
+
 static const char* k_traceMarkerPath =
     "/sys/kernel/debug/tracing/trace_marker";
 
@@ -310,6 +334,12 @@
 // or /sys/ files.
 static bool isCategorySupported(const TracingCategory& category)
 {
+    if (strcmp(category.name, k_coreServiceCategory) == 0) {
+        char value[PROPERTY_VALUE_MAX];
+        property_get(k_coreServicesProp, value, "");
+        return strlen(value) != 0;
+    }
+
     bool ok = category.tags != 0;
     for (int i = 0; i < MAX_SYS_FILES; i++) {
         const char* path = category.sysfiles[i].path;
@@ -476,8 +506,8 @@
 // processes to pick up the new value.
 static bool setTagsProperty(uint64_t tags)
 {
-    char buf[64];
-    snprintf(buf, 64, "%#" PRIx64, tags);
+    char buf[PROPERTY_VALUE_MAX];
+    snprintf(buf, sizeof(buf), "%#" PRIx64, tags);
     if (property_set(k_traceTagsProperty, buf) < 0) {
         fprintf(stderr, "error setting trace tags system property\n");
         return false;
@@ -485,12 +515,53 @@
     return true;
 }
 
+static void clearAppProperties()
+{
+    char buf[PROPERTY_KEY_MAX];
+    for (int i = 0; i < MAX_PACKAGES; i++) {
+        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
+        if (property_set(buf, "") < 0) {
+            fprintf(stderr, "failed to clear system property: %s\n", buf);
+        }
+    }
+    if (property_set(k_traceAppsNumberProperty, "") < 0) {
+        fprintf(stderr, "failed to clear system property: %s",
+              k_traceAppsNumberProperty);
+    }
+}
+
 // Set the system property that indicates which apps should perform
 // application-level tracing.
 static bool setAppCmdlineProperty(const char* cmdline)
 {
-    if (property_set(k_traceAppCmdlineProperty, cmdline) < 0) {
-        fprintf(stderr, "error setting trace app system property\n");
+    char buf[PROPERTY_KEY_MAX];
+    int i = 0;
+    const char* start = cmdline;
+    while (start != NULL) {
+        if (i == MAX_PACKAGES) {
+            fprintf(stderr, "error: only 16 packages could be traced at once\n");
+            clearAppProperties();
+            return false;
+        }
+        char* end = strchr(start, ',');
+        if (end != NULL) {
+            *end = '\0';
+            end++;
+        }
+        snprintf(buf, sizeof(buf), k_traceAppsPropertyTemplate, i);
+        if (property_set(buf, start) < 0) {
+            fprintf(stderr, "error setting trace app %d property to %s\n", i, buf);
+            clearAppProperties();
+            return false;
+        }
+        start = end;
+        i++;
+    }
+
+    snprintf(buf, sizeof(buf), "%d", i);
+    if (property_set(k_traceAppsNumberProperty, buf) < 0) {
+        fprintf(stderr, "error setting trace app number property to %s\n", buf);
+        clearAppProperties();
         return false;
     }
     return true;
@@ -535,17 +606,19 @@
     String8 funcList = String8::format("\n%s", buf);
 
     // Make sure that every function listed in funcs is in the list we just
-    // read from the kernel.
+    // read from the kernel, except for wildcard inputs.
     bool ok = true;
     char* myFuncs = strdup(funcs);
     char* func = strtok(myFuncs, ",");
     while (func) {
-        String8 fancyFunc = String8::format("\n%s\n", func);
-        bool found = funcList.find(fancyFunc.string(), 0) >= 0;
-        if (!found || func[0] == '\0') {
-            fprintf(stderr, "error: \"%s\" is not a valid kernel function "
-                "to trace.\n", func);
-            ok = false;
+        if (!strchr(func, '*')) {
+            String8 fancyFunc = String8::format("\n%s\n", func);
+            bool found = funcList.find(fancyFunc.string(), 0) >= 0;
+            if (!found || func[0] == '\0') {
+                fprintf(stderr, "error: \"%s\" is not a valid kernel function "
+                        "to trace.\n", func);
+                ok = false;
+            }
         }
         func = strtok(NULL, ",");
     }
@@ -594,6 +667,52 @@
     return ok;
 }
 
+static bool setCategoryEnable(const char* name, bool enable)
+{
+    for (int i = 0; i < NELEM(k_categories); i++) {
+        const TracingCategory& c = k_categories[i];
+        if (strcmp(name, c.name) == 0) {
+            if (isCategorySupported(c)) {
+                g_categoryEnables[i] = enable;
+                return true;
+            } else {
+                if (isCategorySupportedForRoot(c)) {
+                    fprintf(stderr, "error: category \"%s\" requires root "
+                            "privileges.\n", name);
+                } else {
+                    fprintf(stderr, "error: category \"%s\" is not supported "
+                            "on this device.\n", name);
+                }
+                return false;
+            }
+        }
+    }
+    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
+    return false;
+}
+
+static bool setCategoriesEnableFromFile(const char* categories_file)
+{
+    if (!categories_file) {
+        return true;
+    }
+    Tokenizer* tokenizer = NULL;
+    if (Tokenizer::open(String8(categories_file), &tokenizer) != NO_ERROR) {
+        return false;
+    }
+    bool ok = true;
+    while (!tokenizer->isEol()) {
+        String8 token = tokenizer->nextToken(" ");
+        if (token.isEmpty()) {
+            tokenizer->skipDelimiters(" ");
+            continue;
+        }
+        ok &= setCategoryEnable(token.string(), true);
+    }
+    delete tokenizer;
+    return ok;
+}
+
 // Set all the kernel tracing settings to the desired state for this trace
 // capture.
 static bool setUpTrace()
@@ -601,6 +720,7 @@
     bool ok = true;
 
     // Set up the tracing options.
+    ok &= setCategoriesEnableFromFile(g_categoriesFile);
     ok &= setTraceOverwriteEnable(g_traceOverwrite);
     ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
     ok &= setGlobalClockEnable(true);
@@ -616,7 +736,24 @@
         }
     }
     ok &= setTagsProperty(tags);
-    ok &= setAppCmdlineProperty(g_debugAppCmdLine);
+
+    bool coreServicesTagEnabled = false;
+    for (int i = 0; i < NELEM(k_categories); i++) {
+        if (strcmp(k_categories[i].name, k_coreServiceCategory) == 0) {
+            coreServicesTagEnabled = g_categoryEnables[i];
+        }
+    }
+
+    std::string packageList(g_debugAppCmdLine);
+    if (coreServicesTagEnabled) {
+        char value[PROPERTY_VALUE_MAX];
+        property_get(k_coreServicesProp, value, "");
+        if (!packageList.empty()) {
+            packageList += ",";
+        }
+        packageList += value;
+    }
+    ok &= setAppCmdlineProperty(packageList.data());
     ok &= pokeBinderServices();
 
     // Disable all the sysfs enables.  This is done as a separate loop from
@@ -653,7 +790,7 @@
 
     // Reset the system properties.
     setTagsProperty(0);
-    setAppCmdlineProperty("");
+    clearAppProperties();
     pokeBinderServices();
 
     // Set the options back to their defaults.
@@ -677,9 +814,35 @@
     setTracingEnabled(false);
 }
 
-// Read the current kernel trace and write it to stdout.
-static void dumpTrace()
+// Read data from the tracing pipe and forward to stdout
+static void streamTrace()
 {
+    char trace_data[4096];
+    int traceFD = open(k_traceStreamPath, O_RDWR);
+    if (traceFD == -1) {
+        fprintf(stderr, "error opening %s: %s (%d)\n", k_traceStreamPath,
+                strerror(errno), errno);
+        return;
+    }
+    while (!g_traceAborted) {
+        ssize_t bytes_read = read(traceFD, trace_data, 4096);
+        if (bytes_read > 0) {
+            write(STDOUT_FILENO, trace_data, bytes_read);
+            fflush(stdout);
+        } else {
+            if (!g_traceAborted) {
+                fprintf(stderr, "read returned %zd bytes err %d (%s)\n",
+                        bytes_read, errno, strerror(errno));
+            }
+            break;
+        }
+    }
+}
+
+// Read the current kernel trace and write it to stdout.
+static void dumpTrace(int outFd)
+{
+    ALOGI("Dumping trace");
     int traceFD = open(k_tracePath, O_RDWR);
     if (traceFD == -1) {
         fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
@@ -728,7 +891,7 @@
 
             if (zs.avail_out == 0) {
                 // Need to write the output.
-                result = write(STDOUT_FILENO, out, bufSize);
+                result = write(outFd, out, bufSize);
                 if ((size_t)result < bufSize) {
                     fprintf(stderr, "error writing deflated trace: %s (%d)\n",
                             strerror(errno), errno);
@@ -748,7 +911,7 @@
 
         if (zs.avail_out < bufSize) {
             size_t bytes = bufSize - zs.avail_out;
-            result = write(STDOUT_FILENO, out, bytes);
+            result = write(outFd, out, bytes);
             if ((size_t)result < bytes) {
                 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
                         strerror(errno), errno);
@@ -764,7 +927,7 @@
         free(out);
     } else {
         ssize_t sent = 0;
-        while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
+        while ((sent = sendfile(outFd, traceFD, NULL, 64*1024*1024)) > 0);
         if (sent == -1) {
             fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
                     errno);
@@ -793,30 +956,6 @@
     sigaction(SIGTERM, &sa, NULL);
 }
 
-static bool setCategoryEnable(const char* name, bool enable)
-{
-    for (int i = 0; i < NELEM(k_categories); i++) {
-        const TracingCategory& c = k_categories[i];
-        if (strcmp(name, c.name) == 0) {
-            if (isCategorySupported(c)) {
-                g_categoryEnables[i] = enable;
-                return true;
-            } else {
-                if (isCategorySupportedForRoot(c)) {
-                    fprintf(stderr, "error: category \"%s\" requires root "
-                            "privileges.\n", name);
-                } else {
-                    fprintf(stderr, "error: category \"%s\" is not supported "
-                            "on this device.\n", name);
-                }
-                return false;
-            }
-        }
-    }
-    fprintf(stderr, "error: unknown tracing category \"%s\"\n", name);
-    return false;
-}
-
 static void listSupportedCategories()
 {
     for (int i = 0; i < NELEM(k_categories); i++) {
@@ -836,6 +975,8 @@
                         "separated list of cmdlines\n"
                     "  -b N            use a trace buffer size of N KB\n"
                     "  -c              trace into a circular buffer\n"
+                    "  -f filename     use the categories written in a file as space-separated\n"
+                    "                    values in a line\n"
                     "  -k fname,...    trace the listed kernel functions\n"
                     "  -n              ignore signals\n"
                     "  -s N            sleep for N seconds before tracing [default 0]\n"
@@ -845,8 +986,14 @@
                     "  --async_dump    dump the current contents of circular trace buffer\n"
                     "  --async_stop    stop tracing and dump the current contents of circular\n"
                     "                    trace buffer\n"
+                    "  --stream        stream trace to stdout as it enters the trace buffer\n"
+                    "                    Note: this can take significant CPU time, and is best\n"
+                    "                    used for measuring things that are not affected by\n"
+                    "                    CPU performance, like pagecache usage.\n"
                     "  --list_categories\n"
                     "                  list the available tracing categories\n"
+                    " -o filename      write the trace to the specified file instead\n"
+                    "                    of stdout.\n"
             );
 }
 
@@ -856,6 +1003,7 @@
     bool traceStart = true;
     bool traceStop = true;
     bool traceDump = true;
+    bool traceStream = false;
 
     if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
         showHelp(argv[0]);
@@ -870,10 +1018,11 @@
             {"async_stop",      no_argument, 0,  0 },
             {"async_dump",      no_argument, 0,  0 },
             {"list_categories", no_argument, 0,  0 },
+            {"stream",          no_argument, 0,  0 },
             {           0,                0, 0,  0 }
         };
 
-        ret = getopt_long(argc, argv, "a:b:ck:ns:t:z",
+        ret = getopt_long(argc, argv, "a:b:cf:k:ns:t:zo:",
                           long_options, &option_index);
 
         if (ret < 0) {
@@ -899,6 +1048,10 @@
                 g_traceOverwrite = true;
             break;
 
+            case 'f':
+                g_categoriesFile = optarg;
+            break;
+
             case 'k':
                 g_kernelTraceFuncs = optarg;
             break;
@@ -919,6 +1072,10 @@
                 g_compress = true;
             break;
 
+            case 'o':
+                g_outputFile = optarg;
+            break;
+
             case 0:
                 if (!strcmp(long_options[option_index].name, "async_start")) {
                     async = true;
@@ -932,6 +1089,9 @@
                     async = true;
                     traceStart = false;
                     traceStop = false;
+                } else if (!strcmp(long_options[option_index].name, "stream")) {
+                    traceStream = true;
+                    traceDump = false;
                 } else if (!strcmp(long_options[option_index].name, "list_categories")) {
                     listSupportedCategories();
                     exit(0);
@@ -957,8 +1117,10 @@
     ok &= startTrace();
 
     if (ok && traceStart) {
-        printf("capturing trace...");
-        fflush(stdout);
+        if (!traceStream) {
+            printf("capturing trace...");
+            fflush(stdout);
+        }
 
         // We clear the trace after starting it because tracing gets enabled for
         // each CPU individually in the kernel. Having the beginning of the trace
@@ -968,7 +1130,7 @@
         ok = clearTrace();
 
         writeClockSyncMarker();
-        if (ok && !async) {
+        if (ok && !async && !traceStream) {
             // Sleep to allow the trace to be captured.
             struct timespec timeLeft;
             timeLeft.tv_sec = g_traceDurationSeconds;
@@ -979,6 +1141,10 @@
                 }
             } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
         }
+
+        if (traceStream) {
+            streamTrace();
+        }
     }
 
     // Stop the trace and restore the default settings.
@@ -987,9 +1153,21 @@
 
     if (ok && traceDump) {
         if (!g_traceAborted) {
-            printf(" done\nTRACE:\n");
+            printf(" done\n");
             fflush(stdout);
-            dumpTrace();
+            int outFd = STDOUT_FILENO;
+            if (g_outputFile) {
+                outFd = open(g_outputFile, O_WRONLY | O_CREAT);
+            }
+            if (outFd == -1) {
+                printf("Failed to open '%s', err=%d", g_outputFile, errno);
+            } else {
+                dprintf(outFd, "TRACE:\n");
+                dumpTrace(outFd);
+                if (g_outputFile) {
+                    close(outFd);
+                }
+            }
         } else {
             printf("\ntrace aborted.\n");
             fflush(stdout);
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
new file mode 100644
index 0000000..c2f8891
--- /dev/null
+++ b/cmds/atrace/atrace.rc
@@ -0,0 +1,71 @@
+## Permissions to allow system-wide tracing to the kernel trace buffer.
+##
+on boot
+
+# Allow writing to the kernel trace log.
+    chmod 0222 /sys/kernel/debug/tracing/trace_marker
+
+# Allow the shell group to enable (some) kernel tracing.
+    chown root shell /sys/kernel/debug/tracing/trace_clock
+    chown root shell /sys/kernel/debug/tracing/buffer_size_kb
+    chown root shell /sys/kernel/debug/tracing/options/overwrite
+    chown root shell /sys/kernel/debug/tracing/options/print-tgid
+    chown root shell /sys/kernel/debug/tracing/events/sched/sched_switch/enable
+    chown root shell /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
+    chown root shell /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
+    chown root shell /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
+    chown root shell /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
+    chown root shell /sys/kernel/debug/tracing/events/power/cpu_idle/enable
+    chown root shell /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
+    chown root shell /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
+    chown root shell /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
+    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
+    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
+    chown root shell /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
+    chown root shell /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
+    chown root shell /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
+    chown root shell /sys/kernel/debug/tracing/events/binder/binder_lock/enable
+    chown root shell /sys/kernel/debug/tracing/events/binder/binder_locked/enable
+    chown root shell /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
+
+    chown root shell /sys/kernel/debug/tracing/tracing_on
+
+    chmod 0664 /sys/kernel/debug/tracing/trace_clock
+    chmod 0664 /sys/kernel/debug/tracing/buffer_size_kb
+    chmod 0664 /sys/kernel/debug/tracing/options/overwrite
+    chmod 0664 /sys/kernel/debug/tracing/options/print-tgid
+    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_switch/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_wakeup/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_blocked_reason/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/sched/sched_cpu_hotplug/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_frequency/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_idle/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/power/clock_set_rate/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/power/cpu_frequency_limits/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/cpufreq_interactive/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_begin/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_direct_reclaim_end/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_wake/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/vmscan/mm_vmscan_kswapd_sleep/enable
+    chmod 0664 /sys/kernel/debug/tracing/tracing_on
+    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_transaction/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_transaction_received/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_lock/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_locked/enable
+    chmod 0664 /sys/kernel/debug/tracing/events/binder/binder_unlock/enable
+
+    # Tracing disabled by default
+    write /sys/kernel/debug/tracing/tracing_on 0
+
+# Allow only the shell group to read and truncate the kernel trace.
+    chown root shell /sys/kernel/debug/tracing/trace
+    chmod 0660 /sys/kernel/debug/tracing/trace
+
+on property:persist.debug.atrace.boottrace=1
+    start boottrace
+
+# Run atrace with the categories written in a file
+service boottrace /system/bin/atrace --async_start -f /data/misc/boottrace/categories
+    disabled
+    oneshot
diff --git a/cmds/bugreport/bugreport.cpp b/cmds/bugreport/bugreport.cpp
index 6892b57..917c813 100644
--- a/cmds/bugreport/bugreport.cpp
+++ b/cmds/bugreport/bugreport.cpp
@@ -28,6 +28,11 @@
 // output. All of the dumpstate output is written to stdout, including
 // any errors encountered while reading/writing the output.
 int main() {
+
+  fprintf(stderr, "=============================================================================\n");
+  fprintf(stderr, "WARNING: flat bugreports are deprecated, use adb bugreport <zip_file> instead\n");
+  fprintf(stderr, "=============================================================================\n\n\n");
+
   // Start the dumpstate service.
   property_set("ctl.start", "dumpstate");
 
diff --git a/cmds/bugreportz/Android.mk b/cmds/bugreportz/Android.mk
new file mode 100644
index 0000000..14ba225
--- /dev/null
+++ b/cmds/bugreportz/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= bugreportz.cpp
+
+LOCAL_MODULE:= bugreportz
+
+LOCAL_CFLAGS := -Wall
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/bugreportz/bugreportz.cpp b/cmds/bugreportz/bugreportz.cpp
new file mode 100644
index 0000000..19d2d64
--- /dev/null
+++ b/cmds/bugreportz/bugreportz.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+
+static constexpr char VERSION[] = "1.0";
+
+static void show_usage() {
+  fprintf(stderr,
+          "usage: bugreportz [-h | -v]\n"
+          "  -h: to display this help message\n"
+          "  -v: to display the version\n"
+          "  or no arguments to generate a zipped bugreport\n");
+}
+
+static void show_version() {
+  fprintf(stderr, "%s\n", VERSION);
+}
+
+int main(int argc, char *argv[]) {
+
+    if (argc > 1) {
+        /* parse arguments */
+        int c;
+        while ((c = getopt(argc, argv, "vh")) != -1) {
+            switch (c) {
+                case 'h':
+                    show_usage();
+                    return EXIT_SUCCESS;
+                case 'v':
+                    show_version();
+                    return EXIT_SUCCESS;
+                default:
+                    show_usage();
+                    return EXIT_FAILURE;
+            }
+        }
+        // passed an argument not starting with -
+        if (optind > 1 || argv[optind] != nullptr) {
+            show_usage();
+            return EXIT_FAILURE;
+        }
+    }
+
+    // TODO: code below was copy-and-pasted from bugreport.cpp (except by the timeout value);
+    // should be reused instead.
+
+    // Start the dumpstatez service.
+    property_set("ctl.start", "dumpstatez");
+
+    // Socket will not be available until service starts.
+    int s;
+    for (int i = 0; i < 20; i++) {
+        s = socket_local_client("dumpstate", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+        if (s >= 0)
+            break;
+        // Try again in 1 second.
+        sleep(1);
+    }
+
+    if (s == -1) {
+        printf("Failed to connect to dumpstatez service: %s\n", strerror(errno));
+        return EXIT_FAILURE;
+    }
+
+    // Set a timeout so that if nothing is read in 10 minutes, we'll stop
+    // reading and quit. No timeout in dumpstate is longer than 60 seconds,
+    // so this gives lots of leeway in case of unforeseen time outs.
+    struct timeval tv;
+    tv.tv_sec = 10 * 60;
+    tv.tv_usec = 0;
+    if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) == -1) {
+        printf("WARNING: Cannot set socket timeout: %s\n", strerror(errno));
+    }
+
+    while (1) {
+        char buffer[65536];
+        ssize_t bytes_read = TEMP_FAILURE_RETRY(
+                read(s, buffer, sizeof(buffer)));
+        if (bytes_read == 0) {
+            break;
+        } else if (bytes_read == -1) {
+            // EAGAIN really means time out, so change the errno.
+            if (errno == EAGAIN) {
+                errno = ETIMEDOUT;
+            }
+            printf("\nBugreport read terminated abnormally (%s).\n",
+                    strerror(errno));
+            break;
+        }
+
+        ssize_t bytes_to_send = bytes_read;
+        ssize_t bytes_written;
+        do {
+            bytes_written = TEMP_FAILURE_RETRY(
+                    write(STDOUT_FILENO, buffer + bytes_read - bytes_to_send,
+                            bytes_to_send));
+            if (bytes_written == -1) {
+                printf(
+                        "Failed to write data to stdout: read %zd, trying to send %zd (%s)\n",
+                        bytes_read, bytes_to_send, strerror(errno));
+                return EXIT_FAILURE;
+            }
+            bytes_to_send -= bytes_written;
+        } while (bytes_written != 0 && bytes_to_send > 0);
+    }
+
+    close(s);
+    return EXIT_SUCCESS;
+}
diff --git a/cmds/bugreportz/readme.md b/cmds/bugreportz/readme.md
new file mode 100644
index 0000000..85aafce
--- /dev/null
+++ b/cmds/bugreportz/readme.md
@@ -0,0 +1,12 @@
+# bugreportz protocol
+
+`bugreportz` is used to generate a zippped bugreport whose path is passed back to `adb`, using
+the simple protocol defined below.
+
+
+## Version 1.0
+On version 1.0, `bugreportz` does not generate any output on `stdout` until the bugreport is
+finished, when it then prints one line with the result:
+
+- `OK:<path_to_bugreport_file>` in case of success.
+- `FAIL:<error message>` in case of failure.
diff --git a/cmds/cmd/Android.mk b/cmds/cmd/Android.mk
new file mode 100644
index 0000000..ac2f4c0
--- /dev/null
+++ b/cmds/cmd/Android.mk
@@ -0,0 +1,20 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	cmd.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libutils \
+	liblog \
+	libbinder
+	
+
+ifeq ($(TARGET_OS),linux)
+	LOCAL_CFLAGS += -DXP_UNIX
+	#LOCAL_SHARED_LIBRARIES += librt
+endif
+
+LOCAL_MODULE:= cmd
+
+include $(BUILD_EXECUTABLE)
diff --git a/cmds/cmd/MODULE_LICENSE_APACHE2 b/cmds/cmd/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/cmds/cmd/MODULE_LICENSE_APACHE2
diff --git a/cmds/cmd/NOTICE b/cmds/cmd/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/cmds/cmd/NOTICE
@@ -0,0 +1,190 @@
+
+   Copyright (c) 2005-2008, The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+
+   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.
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
diff --git a/cmds/cmd/cmd.cpp b/cmds/cmd/cmd.cpp
new file mode 100644
index 0000000..ed740d3
--- /dev/null
+++ b/cmds/cmd/cmd.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "cmd"
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <binder/ProcessState.h>
+#include <binder/IResultReceiver.h>
+#include <binder/IServiceManager.h>
+#include <binder/TextOutput.h>
+#include <utils/Vector.h>
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+using namespace android;
+
+static int sort_func(const String16* lhs, const String16* rhs)
+{
+    return lhs->compare(*rhs);
+}
+
+class MyResultReceiver : public BnResultReceiver
+{
+public:
+    virtual void send(int32_t /*resultCode*/) {
+    }
+};
+
+int main(int argc, char* const argv[])
+{
+    signal(SIGPIPE, SIG_IGN);
+    sp<ProcessState> proc = ProcessState::self();
+    proc->startThreadPool();
+
+    sp<IServiceManager> sm = defaultServiceManager();
+    fflush(stdout);
+    if (sm == NULL) {
+        ALOGE("Unable to get default service manager!");
+        aerr << "cmd: Unable to get default service manager!" << endl;
+        return 20;
+    }
+
+    if (argc == 1) {
+        aout << "cmd: no service specified; use -l to list all services" << endl;
+        return 20;
+    }
+
+    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
+        Vector<String16> services = sm->listServices();
+        services.sort(sort_func);
+        aout << "Currently running services:" << endl;
+
+        for (size_t i=0; i<services.size(); i++) {
+            sp<IBinder> service = sm->checkService(services[i]);
+            if (service != NULL) {
+                aout << "  " << services[i] << endl;
+            }
+        }
+        return 0;
+    }
+
+    Vector<String16> args;
+    for (int i=2; i<argc; i++) {
+        args.add(String16(argv[i]));
+    }
+    String16 cmd = String16(argv[1]);
+    sp<IBinder> service = sm->checkService(cmd);
+    if (service == NULL) {
+        aerr << "Can't find service: " << argv[1] << endl;
+        return 20;
+    }
+
+    // TODO: block until a result is returned to MyResultReceiver.
+    IBinder::shellCommand(service, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, args,
+            new MyResultReceiver());
+    return 0;
+}
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 9065ee1..a588ef4 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -1,6 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := libdumpstate_default.c
+LOCAL_SRC_FILES := libdumpstate_default.cpp
 LOCAL_MODULE := libdumpstate.default
 include $(BUILD_STATIC_LIBRARY)
 
@@ -10,12 +10,15 @@
 LOCAL_CFLAGS := -DFWDUMP_$(BOARD_WLAN_DEVICE)
 endif
 
-LOCAL_SRC_FILES := dumpstate.c utils.c
+LOCAL_SRC_FILES := dumpstate.cpp utils.cpp
 
 LOCAL_MODULE := dumpstate
 
 LOCAL_SHARED_LIBRARIES := libcutils liblog libselinux
+# ZipArchive support, the order matters here to get all symbols.
+LOCAL_STATIC_LIBRARIES := libziparchive libz libbase libmincrypt
 LOCAL_HAL_STATIC_LIBRARIES := libdumpstate
-LOCAL_CFLAGS += -Wall -Wno-unused-parameter -std=gnu99
+LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
+LOCAL_INIT_RC := dumpstate.rc
 
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/bugreport-format.md b/cmds/dumpstate/bugreport-format.md
new file mode 100644
index 0000000..d7837ae
--- /dev/null
+++ b/cmds/dumpstate/bugreport-format.md
@@ -0,0 +1,89 @@
+# Bugreport file format
+
+This document specifies the format of the bugreport files generated by the
+bugreport services (like `bugreport` and `bugreportplus`) and delivered to the
+end user (i.e., it doesn’t include other tools like `adb bugreport`).
+
+A _bugreport_ is initially generated by dumpstate, then processed by **Shell**,
+which in turn delivers it to the end user through a `ACTION_SEND_MULTIPLE`
+intent; the end user then select which app (like an email client) handles such
+intent.
+
+## Text file (Pre-M)
+Prior to _Android M (Marshmallow)_, `dumpstate` generates a flat .txt file named
+_bugreport-DATE.txt_ (where _DATE_ is date the bugreport was generated, in the
+format _YYYY-MM-DD-HH-MM-SS_), and Shell simply propagates it as an attachment
+in the `ACTION_SEND_MULTIPLE` intent.
+
+## Version v0 (Android M)
+On _Android M (Marshmallow)_, dumpstate still generates a flat
+_bugreport-DATE.txt_ file, but then **Shell** creates a zip file called
+_bugreport-DATE.zip_ containing a _bugreport-DATE.txt_ entry and sends that
+file as the `ACTION_SEND_MULTIPLE` attachment.
+
+## Version v1 (Android N)
+On _Android N (TBD)_, `dumpstate` generates a zip file directly (unless there
+is a failure, in which case it reverts to the flat file that is zipped by
+**Shell** and hence the end result is the _v0_ format).
+
+The zip file is by default called _bugreport-BUILD_ID-DATE.zip_ and it contains a
+_bugreport-BUILD_ID-DATE.txt_ entry, although the end user can change the name (through
+**Shell**), in which case they would be called _bugreport-BUILD_ID-NEW_NAME.zip_ and
+_bugreport-BUILD_ID-NEW_NAME.txt_ respectively.
+
+The zip file also contains 2 metadata entries generated by `dumpstate`:
+
+- `version.txt`:  whose value is **v1**.
+- `main-entry.txt`: whose value is the name of the flat text entry (i.e.,
+  _bugreport-BUILD_ID-DATE.txt_ or _bugreport-NEW_NAME.txt_).
+
+`dumpstate` can also copy files from the device’s filesystem into the zip file
+under the `FS` folder. For example, a `/dirA/dirB/fileC` file in the device
+would generate a `FS/dirA/dirB/fileC` entry in the zip file.
+
+When systrace is enabled, the zip file will contain a `systrace.txt` file as well.
+
+The flat file also has some minor changes:
+
+- Tombstone files were removed and added to the zip file.
+- The duration of each section is printed in the report.
+- Some dumpsys sections (memory and cpuinfo) are reported earlier in the file.
+
+Besides the files generated by `dumpstate`, **Shell** can also add 2 other
+files upon the end user’s request:
+
+- `title.txt`: whose value is a single-line summary of the problem.
+- `description.txt`: whose value is a multi-line, detailed description of the problem.
+
+## Intermediate versions
+During development, the versions will be suffixed with _-devX_ or
+_-devX-EXPERIMENTAL_FEATURE_, where _X_ is a number that increases as the
+changes become stable.
+
+For example, the initial version during _Android N_ development was
+**v1-dev1**. When `dumpsys` was split in 2 sections but not all tools were
+ready to parse that format, the version was named **v1-dev2**,
+which had to be passed do `dumpsys` explicitly (i.e., trhough a
+`-V v1-dev2` argument). Once that format became stable and tools
+knew how to parse it, the default version became **v1-dev2**.
+
+Similarly, if changes in the file format are made after the initial release of
+Android defining that format, then a new _sub-version_ will be used.
+For example, if after _Android N_ launches changes are made for the next _N_
+release, the version will be called **v1.1** or something like that.
+
+Determining version and main entry
+-----------------------------------------------
+
+Tools parsing the zipped bugreport file can use the following algorithm to
+determine the bugreport format version and its main entry:
+
+```
+If [entries contain "version.txt"]
+   version = read("version.txt")
+   main_entry = read("main_entry.txt")
+else
+   version = v0
+   main_entry = entries[0]
+fi
+```
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
deleted file mode 100644
index a2e4f4b..0000000
--- a/cmds/dumpstate/dumpstate.c
+++ /dev/null
@@ -1,772 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/capability.h>
-#include <sys/prctl.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-
-#include "private/android_filesystem_config.h"
-
-#define LOG_TAG "dumpstate"
-#include <cutils/log.h>
-
-#include "dumpstate.h"
-
-/* read before root is shed */
-static char cmdline_buf[16384] = "(unknown)";
-static const char *dump_traces_path = NULL;
-
-static char screenshot_path[PATH_MAX] = "";
-
-#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
-
-#define RAFT_DIR "/data/misc/raft/"
-#define TOMBSTONE_DIR "/data/tombstones"
-#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
-/* Can accomodate a tombstone number up to 9999. */
-#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
-#define NUM_TOMBSTONES  10
-
-typedef struct {
-  char name[TOMBSTONE_MAX_LEN];
-  int fd;
-} tombstone_data_t;
-
-static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
-
-/* Get the fds of any tombstone that was modified in the last half an hour. */
-static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
-    time_t thirty_minutes_ago = time(NULL) - 60*30;
-    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
-        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
-        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
-                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
-        struct stat st;
-        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
-                (time_t) st.st_mtime >= thirty_minutes_ago) {
-            data[i].fd = fd;
-        } else {
-            close(fd);
-            data[i].fd = -1;
-        }
-    }
-}
-
-static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
-{
-    DIR *d;
-    struct dirent *de;
-    char path[PATH_MAX];
-
-    d = opendir(driverpath);
-    if (d == NULL) {
-        return;
-    }
-
-    while ((de = readdir(d))) {
-        if (de->d_type != DT_LNK) {
-            continue;
-        }
-        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
-        dump_file(title, path);
-    }
-
-    closedir(d);
-}
-
-static bool skip_not_stat(const char *path) {
-    static const char stat[] = "/stat";
-    size_t len = strlen(path);
-    if (path[len - 1] == '/') { /* Directory? */
-        return false;
-    }
-    return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
-}
-
-static const char mmcblk0[] = "/sys/block/mmcblk0/";
-unsigned long worst_write_perf = 20000; /* in KB/s */
-
-static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
-    unsigned long fields[11], read_perf, write_perf;
-    bool z;
-    char *cp, *buffer = NULL;
-    size_t i = 0;
-    FILE *fp = fdopen(fd, "rb");
-    getline(&buffer, &i, fp);
-    fclose(fp);
-    if (!buffer) {
-        return -errno;
-    }
-    i = strlen(buffer);
-    while ((i > 0) && (buffer[i - 1] == '\n')) {
-        buffer[--i] = '\0';
-    }
-    if (!*buffer) {
-        free(buffer);
-        return 0;
-    }
-    z = true;
-    for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
-        fields[i] = strtol(cp, &cp, 0);
-        if (fields[i] != 0) {
-            z = false;
-        }
-    }
-    if (z) { /* never accessed */
-        free(buffer);
-        return 0;
-    }
-
-    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
-        path += sizeof(mmcblk0) - 1;
-    }
-
-    printf("%s: %s\n", path, buffer);
-    free(buffer);
-
-    read_perf = 0;
-    if (fields[3]) {
-        read_perf = 512 * fields[2] / fields[3];
-    }
-    write_perf = 0;
-    if (fields[7]) {
-        write_perf = 512 * fields[6] / fields[7];
-    }
-    printf("%s: read: %luKB/s write: %luKB/s\n", path, read_perf, write_perf);
-    if ((write_perf > 1) && (write_perf < worst_write_perf)) {
-        worst_write_perf = write_perf;
-    }
-    return 0;
-}
-
-/* Copied policy from system/core/logd/LogBuffer.cpp */
-
-#define LOG_BUFFER_SIZE (256 * 1024)
-#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
-#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
-
-static bool valid_size(unsigned long value) {
-    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
-        return false;
-    }
-
-    long pages = sysconf(_SC_PHYS_PAGES);
-    if (pages < 1) {
-        return true;
-    }
-
-    long pagesize = sysconf(_SC_PAGESIZE);
-    if (pagesize <= 1) {
-        pagesize = PAGE_SIZE;
-    }
-
-    // maximum memory impact a somewhat arbitrary ~3%
-    pages = (pages + 31) / 32;
-    unsigned long maximum = pages * pagesize;
-
-    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
-        return true;
-    }
-
-    return value <= maximum;
-}
-
-static unsigned long property_get_size(const char *key) {
-    unsigned long value;
-    char *cp, property[PROPERTY_VALUE_MAX];
-
-    property_get(key, property, "");
-    value = strtoul(property, &cp, 10);
-
-    switch(*cp) {
-    case 'm':
-    case 'M':
-        value *= 1024;
-    /* FALLTHRU */
-    case 'k':
-    case 'K':
-        value *= 1024;
-    /* FALLTHRU */
-    case '\0':
-        break;
-
-    default:
-        value = 0;
-    }
-
-    if (!valid_size(value)) {
-        value = 0;
-    }
-
-    return value;
-}
-
-/* timeout in ms */
-static unsigned long logcat_timeout(char *name) {
-    static const char global_tuneable[] = "persist.logd.size"; // Settings App
-    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
-    char key[PROP_NAME_MAX];
-    unsigned long property_size, default_size;
-
-    default_size = property_get_size(global_tuneable);
-    if (!default_size) {
-        default_size = property_get_size(global_default);
-    }
-
-    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
-    property_size = property_get_size(key);
-
-    if (!property_size) {
-        snprintf(key, sizeof(key), "%s.%s", global_default, name);
-        property_size = property_get_size(key);
-    }
-
-    if (!property_size) {
-        property_size = default_size;
-    }
-
-    if (!property_size) {
-        property_size = LOG_BUFFER_SIZE;
-    }
-
-    /* Engineering margin is ten-fold our guess */
-    return 10 * (property_size + worst_write_perf) / worst_write_perf;
-}
-
-/* End copy from system/core/logd/LogBuffer.cpp */
-
-static const unsigned long logcat_min_timeout = 40000; /* ms */
-
-/* dumps the current system state to stdout */
-static void dumpstate() {
-    unsigned long timeout;
-    time_t now = time(NULL);
-    char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
-    char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
-    char network[PROPERTY_VALUE_MAX], date[80];
-    char build_type[PROPERTY_VALUE_MAX];
-
-    property_get("ro.build.display.id", build, "(unknown)");
-    property_get("ro.build.fingerprint", fingerprint, "(unknown)");
-    property_get("ro.build.type", build_type, "(unknown)");
-    property_get("ro.baseband", radio, "(unknown)");
-    property_get("ro.bootloader", bootloader, "(unknown)");
-    property_get("gsm.operator.alpha", network, "(unknown)");
-    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
-
-    printf("========================================================\n");
-    printf("== dumpstate: %s\n", date);
-    printf("========================================================\n");
-
-    printf("\n");
-    printf("Build: %s\n", build);
-    printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
-    printf("Bootloader: %s\n", bootloader);
-    printf("Radio: %s\n", radio);
-    printf("Network: %s\n", network);
-
-    printf("Kernel: ");
-    dump_file(NULL, "/proc/version");
-    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
-    printf("\n");
-
-    dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
-    run_command("UPTIME", 10, "uptime", NULL);
-    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
-    dump_file("MEMORY INFO", "/proc/meminfo");
-    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-t", NULL);
-    run_command("PROCRANK", 20, "procrank", NULL);
-    dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
-    dump_file("VMALLOC INFO", "/proc/vmallocinfo");
-    dump_file("SLAB INFO", "/proc/slabinfo");
-    dump_file("ZONEINFO", "/proc/zoneinfo");
-    dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
-    dump_file("BUDDYINFO", "/proc/buddyinfo");
-    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
-
-    dump_file("KERNEL WAKELOCKS", "/proc/wakelocks");
-    dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
-    dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
-    dump_file("KERNEL SYNC", "/d/sync");
-
-    run_command("PROCESSES", 10, "ps", "-P", NULL);
-    run_command("PROCESSES AND THREADS", 10, "ps", "-t", "-p", "-P", NULL);
-    run_command("PROCESSES (SELINUX LABELS)", 10, "ps", "-Z", NULL);
-    run_command("LIBRANK", 10, "librank", NULL);
-
-    do_dmesg();
-
-    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
-    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
-    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
-
-    if (screenshot_path[0]) {
-        ALOGI("taking screenshot\n");
-        run_command(NULL, 10, "/system/bin/screencap", "-p", screenshot_path, NULL);
-        ALOGI("wrote screenshot: %s\n", screenshot_path);
-    }
-
-    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
-    // calculate timeout
-    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
-    if (timeout < logcat_min_timeout) {
-        timeout = logcat_min_timeout;
-    }
-    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
-    timeout = logcat_timeout("events");
-    if (timeout < logcat_min_timeout) {
-        timeout = logcat_min_timeout;
-    }
-    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
-    timeout = logcat_timeout("radio");
-    if (timeout < logcat_min_timeout) {
-        timeout = logcat_min_timeout;
-    }
-    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
-
-    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
-
-    run_command("RAFT LOGS", 600, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
-
-    /* show the traces we collected in main(), if that was done */
-    if (dump_traces_path != NULL) {
-        dump_file("VM TRACES JUST NOW", dump_traces_path);
-    }
-
-    /* only show ANR traces if they're less than 15 minutes old */
-    struct stat st;
-    char anr_traces_path[PATH_MAX];
-    property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
-    if (!anr_traces_path[0]) {
-        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
-    } else {
-      int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
-                                       O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
-      if (fd < 0) {
-          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
-      } else {
-          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
-      }
-    }
-
-    /* slow traces for slow operations */
-    if (anr_traces_path[0] != 0) {
-        int tail = strlen(anr_traces_path)-1;
-        while (tail > 0 && anr_traces_path[tail] != '/') {
-            tail--;
-        }
-        int i = 0;
-        while (1) {
-            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
-            if (stat(anr_traces_path, &st)) {
-                // No traces file at this index, done with the files.
-                break;
-            }
-            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
-            i++;
-        }
-    }
-
-    int dumped = 0;
-    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
-        if (tombstone_data[i].fd != -1) {
-            dumped = 1;
-            dump_file_from_fd("TOMBSTONE", tombstone_data[i].name, tombstone_data[i].fd);
-            tombstone_data[i].fd = -1;
-        }
-    }
-    if (!dumped) {
-        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
-    }
-
-    dump_file("NETWORK DEV INFO", "/proc/net/dev");
-    dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
-    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
-    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
-    dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
-
-    if (!stat(PSTORE_LAST_KMSG, &st)) {
-        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
-        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
-    } else {
-        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
-        dump_file("LAST KMSG", "/proc/last_kmsg");
-    }
-
-    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
-    run_command("LAST LOGCAT", 10, "logcat", "-L", "-v", "threadtime",
-                                             "-b", "all", "-d", "*:v", NULL);
-
-    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
-
-    run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
-
-    run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
-    run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
-
-    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
-    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
-
-    dump_route_tables();
-
-    run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
-    run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
-
-    run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
-    run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
-    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
-    /* no ip6 nat */
-    run_command("IPTABLE RAW", 10, SU_PATH, "root", "iptables", "-t", "raw", "-L", "-nvx", NULL);
-    run_command("IP6TABLE RAW", 10, SU_PATH, "root", "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
-
-    run_command("WIFI NETWORKS", 20,
-            SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
-
-#ifdef FWDUMP_bcmdhd
-    run_command("ND OFFLOAD TABLE", 5,
-            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
-
-    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
-            SU_PATH, "root", "wlutil", "counters", NULL);
-
-    run_command("ND OFFLOAD STATUS (1)", 5,
-            SU_PATH, "root", "wlutil", "nd_status", NULL);
-
-#endif
-    dump_file("INTERRUPTS (1)", "/proc/interrupts");
-
-    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
-
-#ifdef FWDUMP_bcmdhd
-    run_command("DUMP WIFI STATUS", 20,
-            SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
-
-    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
-            SU_PATH, "root", "wlutil", "counters", NULL);
-
-    run_command("ND OFFLOAD STATUS (2)", 5,
-            SU_PATH, "root", "wlutil", "nd_status", NULL);
-#endif
-    dump_file("INTERRUPTS (2)", "/proc/interrupts");
-
-    print_properties();
-
-    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
-    run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
-
-    run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
-
-    run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
-
-    printf("------ BACKLIGHTS ------\n");
-    printf("LCD brightness=");
-    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
-    printf("Button brightness=");
-    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
-    printf("Keyboard brightness=");
-    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
-    printf("ALS mode=");
-    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
-    printf("LCD driver registers:\n");
-    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
-    printf("\n");
-
-    /* Binder state is expensive to look at as it uses a lot of memory. */
-    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
-    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
-    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
-    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
-    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
-
-    printf("========================================================\n");
-    printf("== Board\n");
-    printf("========================================================\n");
-
-    dumpstate_board();
-    printf("\n");
-
-    /* Migrate the ril_dumpstate to a dumpstate_board()? */
-    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
-    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
-    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
-        if (0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1)) {
-            // su does not exist on user builds, so try running without it.
-            // This way any implementations of vril-dump that do not require
-            // root can run on user builds.
-            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
-                    "vril-dump", NULL);
-        } else {
-            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
-                    SU_PATH, "root", "vril-dump", NULL);
-        }
-    }
-
-    printf("========================================================\n");
-    printf("== Android Framework Services\n");
-    printf("========================================================\n");
-
-    /* the full dumpsys is starting to take a long time, so we need
-       to increase its timeout.  we really need to do the timeouts in
-       dumpsys itself... */
-    run_command("DUMPSYS", 60, "dumpsys", NULL);
-
-    printf("========================================================\n");
-    printf("== Checkins\n");
-    printf("========================================================\n");
-
-    run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "batterystats", "-c", NULL);
-    run_command("CHECKIN MEMINFO", 30, "dumpsys", "meminfo", "--checkin", NULL);
-    run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
-    run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
-    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
-    run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL);
-
-    printf("========================================================\n");
-    printf("== Running Application Activities\n");
-    printf("========================================================\n");
-
-    run_command("APP ACTIVITIES", 30, "dumpsys", "activity", "all", NULL);
-
-    printf("========================================================\n");
-    printf("== Running Application Services\n");
-    printf("========================================================\n");
-
-    run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
-
-    printf("========================================================\n");
-    printf("== Running Application Providers\n");
-    printf("========================================================\n");
-
-    run_command("APP SERVICES", 30, "dumpsys", "activity", "provider", "all", NULL);
-
-
-    printf("========================================================\n");
-    printf("== dumpstate: done\n");
-    printf("========================================================\n");
-}
-
-static void usage() {
-    fprintf(stderr, "usage: dumpstate [-b soundfile] [-e soundfile] [-o file [-d] [-p] [-z]] [-s] [-q]\n"
-            "  -o: write to file (instead of stdout)\n"
-            "  -d: append date to filename (requires -o)\n"
-            "  -p: capture screenshot to filename.png (requires -o)\n"
-            "  -s: write output to control socket (for init)\n"
-            "  -b: play sound file instead of vibrate, at beginning of job\n"
-            "  -e: play sound file instead of vibrate, at end of job\n"
-            "  -q: disable vibrate\n"
-            "  -B: send broadcast when finished (requires -o and -p)\n"
-                );
-}
-
-static void sigpipe_handler(int n) {
-    // don't complain to stderr or stdout
-    _exit(EXIT_FAILURE);
-}
-
-static void vibrate(FILE* vibrator, int ms) {
-    fprintf(vibrator, "%d\n", ms);
-    fflush(vibrator);
-}
-
-int main(int argc, char *argv[]) {
-    struct sigaction sigact;
-    int do_add_date = 0;
-    int do_vibrate = 1;
-    char* use_outfile = 0;
-    int use_socket = 0;
-    int do_fb = 0;
-    int do_broadcast = 0;
-
-    if (getuid() != 0) {
-        // Old versions of the adb client would call the
-        // dumpstate command directly. Newer clients
-        // call /system/bin/bugreport instead. If we detect
-        // we're being called incorrectly, then exec the
-        // correct program.
-        return execl("/system/bin/bugreport", "/system/bin/bugreport", NULL);
-    }
-
-    ALOGI("begin\n");
-
-    /* clear SIGPIPE handler */
-    memset(&sigact, 0, sizeof(sigact));
-    sigact.sa_handler = sigpipe_handler;
-    sigaction(SIGPIPE, &sigact, NULL);
-
-    /* set as high priority, and protect from OOM killer */
-    setpriority(PRIO_PROCESS, 0, -20);
-    FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
-    if (oom_adj) {
-        fputs("-17", oom_adj);
-        fclose(oom_adj);
-    }
-
-    /* parse arguments */
-    int c;
-    while ((c = getopt(argc, argv, "dho:svqzpB")) != -1) {
-        switch (c) {
-            case 'd': do_add_date = 1;       break;
-            case 'o': use_outfile = optarg;  break;
-            case 's': use_socket = 1;        break;
-            case 'v': break;  // compatibility no-op
-            case 'q': do_vibrate = 0;        break;
-            case 'p': do_fb = 1;             break;
-            case 'B': do_broadcast = 1;      break;
-            case '?': printf("\n");
-            case 'h':
-                usage();
-                exit(1);
-        }
-    }
-
-    // If we are going to use a socket, do it as early as possible
-    // to avoid timeouts from bugreport.
-    if (use_socket) {
-        redirect_to_socket(stdout, "dumpstate");
-    }
-
-    /* open the vibrator before dropping root */
-    FILE *vibrator = 0;
-    if (do_vibrate) {
-        vibrator = fopen("/sys/class/timed_output/vibrator/enable", "we");
-        if (vibrator) {
-            vibrate(vibrator, 150);
-        }
-    }
-
-    /* read /proc/cmdline before dropping root */
-    FILE *cmdline = fopen("/proc/cmdline", "re");
-    if (cmdline != NULL) {
-        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
-        fclose(cmdline);
-    }
-
-    /* collect stack traces from Dalvik and native processes (needs root) */
-    dump_traces_path = dump_traces();
-
-    /* Get the tombstone fds here while we are running as root. */
-    get_tombstone_fds(tombstone_data);
-
-    /* ensure we will keep capabilities when we drop root */
-    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
-        ALOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
-        return -1;
-    }
-
-    /* switch to non-root user and group */
-    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
-            AID_MOUNT, AID_INET, AID_NET_BW_STATS };
-    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
-        ALOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
-        return -1;
-    }
-    if (setgid(AID_SHELL) != 0) {
-        ALOGE("Unable to setgid, aborting: %s\n", strerror(errno));
-        return -1;
-    }
-    if (setuid(AID_SHELL) != 0) {
-        ALOGE("Unable to setuid, aborting: %s\n", strerror(errno));
-        return -1;
-    }
-
-    struct __user_cap_header_struct capheader;
-    struct __user_cap_data_struct capdata[2];
-    memset(&capheader, 0, sizeof(capheader));
-    memset(&capdata, 0, sizeof(capdata));
-    capheader.version = _LINUX_CAPABILITY_VERSION_3;
-    capheader.pid = 0;
-
-    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
-    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
-    capdata[0].inheritable = 0;
-    capdata[1].inheritable = 0;
-
-    if (capset(&capheader, &capdata[0]) < 0) {
-        ALOGE("capset failed: %s\n", strerror(errno));
-        return -1;
-    }
-
-    /* redirect output if needed */
-    char path[PATH_MAX], tmp_path[PATH_MAX];
-    pid_t gzip_pid = -1;
-
-    if (!use_socket && use_outfile) {
-        strlcpy(path, use_outfile, sizeof(path));
-        if (do_add_date) {
-            char date[80];
-            time_t now = time(NULL);
-            strftime(date, sizeof(date), "-%Y-%m-%d-%H-%M-%S", localtime(&now));
-            strlcat(path, date, sizeof(path));
-        }
-        if (do_fb) {
-            strlcpy(screenshot_path, path, sizeof(screenshot_path));
-            strlcat(screenshot_path, ".png", sizeof(screenshot_path));
-        }
-        strlcat(path, ".txt", sizeof(path));
-        strlcpy(tmp_path, path, sizeof(tmp_path));
-        strlcat(tmp_path, ".tmp", sizeof(tmp_path));
-        redirect_to_file(stdout, tmp_path);
-    }
-
-    dumpstate();
-
-    /* done */
-    if (vibrator) {
-        for (int i = 0; i < 3; i++) {
-            vibrate(vibrator, 75);
-            usleep((75 + 50) * 1000);
-        }
-        fclose(vibrator);
-    }
-
-    /* wait for gzip to finish, otherwise it might get killed when we exit */
-    if (gzip_pid > 0) {
-        fclose(stdout);
-        waitpid(gzip_pid, NULL, 0);
-    }
-
-    /* rename the (now complete) .tmp file to its final location */
-    if (use_outfile && rename(tmp_path, path)) {
-        fprintf(stderr, "rename(%s, %s): %s\n", tmp_path, path, strerror(errno));
-    }
-
-    /* tell activity manager we're done */
-    if (do_broadcast && use_outfile && do_fb) {
-        run_command(NULL, 5, "/system/bin/am", "broadcast", "--user", "0",
-                "-a", "android.intent.action.BUGREPORT_FINISHED",
-                "--es", "android.intent.extra.BUGREPORT", path,
-                "--es", "android.intent.extra.SCREENSHOT", screenshot_path,
-                "--receiver-permission", "android.permission.DUMP", NULL);
-    }
-
-    ALOGI("done\n");
-
-    return 0;
-}
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
new file mode 100644
index 0000000..b731c53
--- /dev/null
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -0,0 +1,1434 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <limits.h>
+#include <memory>
+#include <regex>
+#include <set>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
+
+#include "private/android_filesystem_config.h"
+
+#define LOG_TAG "dumpstate"
+#include <cutils/log.h>
+
+#include "dumpstate.h"
+#include "ScopedFd.h"
+#include "ziparchive/zip_writer.h"
+
+#include "mincrypt/sha256.h"
+
+using android::base::StringPrintf;
+
+/* read before root is shed */
+static char cmdline_buf[16384] = "(unknown)";
+static const char *dump_traces_path = NULL;
+
+// TODO: should be part of dumpstate object
+static unsigned long id;
+static char build_type[PROPERTY_VALUE_MAX];
+static time_t now;
+static std::unique_ptr<ZipWriter> zip_writer;
+static std::set<std::string> mount_points;
+void add_mountinfo();
+static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path);
+static bool add_zip_entry_from_fd(const std::string& entry_name, int fd);
+static int control_socket_fd;
+
+#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops"
+
+#define RAFT_DIR "/data/misc/raft/"
+#define RECOVERY_DIR "/cache/recovery"
+#define RECOVERY_DATA_DIR "/data/misc/recovery"
+#define LOGPERSIST_DATA_DIR "/data/misc/logd"
+#define TOMBSTONE_DIR "/data/tombstones"
+#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_"
+/* Can accomodate a tombstone number up to 9999. */
+#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4)
+#define NUM_TOMBSTONES  10
+
+typedef struct {
+  char name[TOMBSTONE_MAX_LEN];
+  int fd;
+} tombstone_data_t;
+
+static tombstone_data_t tombstone_data[NUM_TOMBSTONES];
+
+// Root dir for all files copied as-is into the bugreport
+const std::string& ZIP_ROOT_DIR = "FS";
+
+/*
+ * List of supported zip format versions.
+ *
+ * See bugreport-format.txt for more info.
+ */
+// TODO: change to "v1" before final N build
+static std::string VERSION_DEFAULT = "v1-dev4";
+
+static bool is_user_build() {
+    return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1);
+}
+
+/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones,
+ * otherwise gets just those modified in the last half an hour. */
+static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) {
+    time_t thirty_minutes_ago = now - 60*30;
+    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
+        snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i);
+        int fd = TEMP_FAILURE_RETRY(open(data[i].name,
+                                         O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
+        struct stat st;
+        if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) &&
+            (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) {
+        data[i].fd = fd;
+        } else {
+        close(fd);
+            data[i].fd = -1;
+        }
+    }
+}
+
+// for_each_pid() callback to get mount info about a process.
+void do_mountinfo(int pid, const char *name) {
+    char path[PATH_MAX];
+
+    // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points
+    // are added.
+    sprintf(path, "/proc/%d/ns/mnt", pid);
+    char linkname[PATH_MAX];
+    ssize_t r = readlink(path, linkname, PATH_MAX);
+    if (r == -1) {
+        MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno));
+        return;
+    }
+    linkname[r] = '\0';
+
+    if (mount_points.find(linkname) == mount_points.end()) {
+        // First time this mount point was found: add it
+        sprintf(path, "/proc/%d/mountinfo", pid);
+        if (add_zip_entry(ZIP_ROOT_DIR + path, path)) {
+            mount_points.insert(linkname);
+        } else {
+            MYLOGE("Unable to add mountinfo %s to zip file\n", path);
+        }
+    }
+}
+
+void add_mountinfo() {
+    if (!zip_writer) return;
+    const char *title = "MOUNT INFO";
+    mount_points.clear();
+    DurationReporter duration_reporter(title, NULL);
+    for_each_pid(do_mountinfo, NULL);
+    MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size());
+}
+
+static void dump_dev_files(const char *title, const char *driverpath, const char *filename)
+{
+    DIR *d;
+    struct dirent *de;
+    char path[PATH_MAX];
+
+    d = opendir(driverpath);
+    if (d == NULL) {
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        if (de->d_type != DT_LNK) {
+            continue;
+        }
+        snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename);
+        dump_file(title, path);
+    }
+
+    closedir(d);
+}
+
+static void dump_systrace(const std::string& systrace_path) {
+    if (!zip_writer) {
+        MYLOGD("Not dumping systrace because zip_writer is not set\n");
+        return;
+    }
+    if (systrace_path.empty()) {
+        MYLOGE("Not dumping systrace because path is empty\n");
+        return;
+    }
+    const char* path = "/sys/kernel/debug/tracing/tracing_on";
+    long int is_tracing;
+    if (read_file_as_long(path, &is_tracing)) {
+        return; // error already logged
+    }
+    if (is_tracing <= 0) {
+        MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing);
+        return;
+    }
+
+    MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes",
+            systrace_path.c_str());
+    if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o",
+            systrace_path.c_str(), NULL)) {
+        MYLOGE("systrace timed out, its zip entry will be incomplete\n");
+        // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally,
+        // we should call strace to stop itself, but there is no such option yet (just a
+        // --async_stop, which stops and dump
+        //        if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) {
+        //            MYLOGE("could not stop systrace ");
+        //        }
+    }
+    if (!add_zip_entry("systrace.txt", systrace_path)) {
+        MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str());
+    } else {
+        if (remove(systrace_path.c_str())) {
+            MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno));
+        }
+    }
+}
+
+static bool skip_not_stat(const char *path) {
+    static const char stat[] = "/stat";
+    size_t len = strlen(path);
+    if (path[len - 1] == '/') { /* Directory? */
+        return false;
+    }
+    return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */
+}
+
+static bool skip_none(const char *path) {
+    return false;
+}
+
+static const char mmcblk0[] = "/sys/block/mmcblk0/";
+unsigned long worst_write_perf = 20000; /* in KB/s */
+
+//
+//  stat offsets
+// Name            units         description
+// ----            -----         -----------
+// read I/Os       requests      number of read I/Os processed
+#define __STAT_READ_IOS      0
+// read merges     requests      number of read I/Os merged with in-queue I/O
+#define __STAT_READ_MERGES   1
+// read sectors    sectors       number of sectors read
+#define __STAT_READ_SECTORS  2
+// read ticks      milliseconds  total wait time for read requests
+#define __STAT_READ_TICKS    3
+// write I/Os      requests      number of write I/Os processed
+#define __STAT_WRITE_IOS     4
+// write merges    requests      number of write I/Os merged with in-queue I/O
+#define __STAT_WRITE_MERGES  5
+// write sectors   sectors       number of sectors written
+#define __STAT_WRITE_SECTORS 6
+// write ticks     milliseconds  total wait time for write requests
+#define __STAT_WRITE_TICKS   7
+// in_flight       requests      number of I/Os currently in flight
+#define __STAT_IN_FLIGHT     8
+// io_ticks        milliseconds  total time this block device has been active
+#define __STAT_IO_TICKS      9
+// time_in_queue   milliseconds  total wait time for all requests
+#define __STAT_IN_QUEUE     10
+#define __STAT_NUMBER_FIELD 11
+//
+// read I/Os, write I/Os
+// =====================
+//
+// These values increment when an I/O request completes.
+//
+// read merges, write merges
+// =========================
+//
+// These values increment when an I/O request is merged with an
+// already-queued I/O request.
+//
+// read sectors, write sectors
+// ===========================
+//
+// These values count the number of sectors read from or written to this
+// block device.  The "sectors" in question are the standard UNIX 512-byte
+// sectors, not any device- or filesystem-specific block size.  The
+// counters are incremented when the I/O completes.
+#define SECTOR_SIZE 512
+//
+// read ticks, write ticks
+// =======================
+//
+// These values count the number of milliseconds that I/O requests have
+// waited on this block device.  If there are multiple I/O requests waiting,
+// these values will increase at a rate greater than 1000/second; for
+// example, if 60 read requests wait for an average of 30 ms, the read_ticks
+// field will increase by 60*30 = 1800.
+//
+// in_flight
+// =========
+//
+// This value counts the number of I/O requests that have been issued to
+// the device driver but have not yet completed.  It does not include I/O
+// requests that are in the queue but not yet issued to the device driver.
+//
+// io_ticks
+// ========
+//
+// This value counts the number of milliseconds during which the device has
+// had I/O requests queued.
+//
+// time_in_queue
+// =============
+//
+// This value counts the number of milliseconds that I/O requests have waited
+// on this block device.  If there are multiple I/O requests waiting, this
+// value will increase as the product of the number of milliseconds times the
+// number of requests waiting (see "read ticks" above for an example).
+#define S_TO_MS 1000
+//
+
+static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) {
+    unsigned long long fields[__STAT_NUMBER_FIELD];
+    bool z;
+    char *cp, *buffer = NULL;
+    size_t i = 0;
+    FILE *fp = fdopen(fd, "rb");
+    getline(&buffer, &i, fp);
+    fclose(fp);
+    if (!buffer) {
+        return -errno;
+    }
+    i = strlen(buffer);
+    while ((i > 0) && (buffer[i - 1] == '\n')) {
+        buffer[--i] = '\0';
+    }
+    if (!*buffer) {
+        free(buffer);
+        return 0;
+    }
+    z = true;
+    for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) {
+        fields[i] = strtoull(cp, &cp, 10);
+        if (fields[i] != 0) {
+            z = false;
+        }
+    }
+    if (z) { /* never accessed */
+        free(buffer);
+        return 0;
+    }
+
+    if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) {
+        path += sizeof(mmcblk0) - 1;
+    }
+
+    printf("%s: %s\n", path, buffer);
+    free(buffer);
+
+    if (fields[__STAT_IO_TICKS]) {
+        unsigned long read_perf = 0;
+        unsigned long read_ios = 0;
+        if (fields[__STAT_READ_TICKS]) {
+            unsigned long long divisor = fields[__STAT_READ_TICKS]
+                                       * fields[__STAT_IO_TICKS];
+            read_perf = ((unsigned long long)SECTOR_SIZE
+                           * fields[__STAT_READ_SECTORS]
+                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
+                                        / divisor;
+            read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS]
+                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
+                                        / divisor;
+        }
+
+        unsigned long write_perf = 0;
+        unsigned long write_ios = 0;
+        if (fields[__STAT_WRITE_TICKS]) {
+            unsigned long long divisor = fields[__STAT_WRITE_TICKS]
+                                       * fields[__STAT_IO_TICKS];
+            write_perf = ((unsigned long long)SECTOR_SIZE
+                           * fields[__STAT_WRITE_SECTORS]
+                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
+                                        / divisor;
+            write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS]
+                           * fields[__STAT_IN_QUEUE] + (divisor >> 1))
+                                        / divisor;
+        }
+
+        unsigned queue = (fields[__STAT_IN_QUEUE]
+                             + (fields[__STAT_IO_TICKS] >> 1))
+                                 / fields[__STAT_IO_TICKS];
+
+        if (!write_perf && !write_ios) {
+            printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n",
+                   path, read_perf, read_ios, queue);
+        } else {
+            printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n",
+                   path, read_perf, read_ios, write_perf, write_ios, queue);
+        }
+
+        /* bugreport timeout factor adjustment */
+        if ((write_perf > 1) && (write_perf < worst_write_perf)) {
+            worst_write_perf = write_perf;
+        }
+    }
+    return 0;
+}
+
+/* Copied policy from system/core/logd/LogBuffer.cpp */
+
+#define LOG_BUFFER_SIZE (256 * 1024)
+#define LOG_BUFFER_MIN_SIZE (64 * 1024UL)
+#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL)
+
+static bool valid_size(unsigned long value) {
+    if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) {
+        return false;
+    }
+
+    long pages = sysconf(_SC_PHYS_PAGES);
+    if (pages < 1) {
+        return true;
+    }
+
+    long pagesize = sysconf(_SC_PAGESIZE);
+    if (pagesize <= 1) {
+        pagesize = PAGE_SIZE;
+    }
+
+    // maximum memory impact a somewhat arbitrary ~3%
+    pages = (pages + 31) / 32;
+    unsigned long maximum = pages * pagesize;
+
+    if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) {
+        return true;
+    }
+
+    return value <= maximum;
+}
+
+static unsigned long property_get_size(const char *key) {
+    unsigned long value;
+    char *cp, property[PROPERTY_VALUE_MAX];
+
+    property_get(key, property, "");
+    value = strtoul(property, &cp, 10);
+
+    switch(*cp) {
+    case 'm':
+    case 'M':
+        value *= 1024;
+    /* FALLTHRU */
+    case 'k':
+    case 'K':
+        value *= 1024;
+    /* FALLTHRU */
+    case '\0':
+        break;
+
+    default:
+        value = 0;
+    }
+
+    if (!valid_size(value)) {
+        value = 0;
+    }
+
+    return value;
+}
+
+/* timeout in ms */
+static unsigned long logcat_timeout(const char *name) {
+    static const char global_tuneable[] = "persist.logd.size"; // Settings App
+    static const char global_default[] = "ro.logd.size";       // BoardConfig.mk
+    char key[PROP_NAME_MAX];
+    unsigned long property_size, default_size;
+
+    default_size = property_get_size(global_tuneable);
+    if (!default_size) {
+        default_size = property_get_size(global_default);
+    }
+
+    snprintf(key, sizeof(key), "%s.%s", global_tuneable, name);
+    property_size = property_get_size(key);
+
+    if (!property_size) {
+        snprintf(key, sizeof(key), "%s.%s", global_default, name);
+        property_size = property_get_size(key);
+    }
+
+    if (!property_size) {
+        property_size = default_size;
+    }
+
+    if (!property_size) {
+        property_size = LOG_BUFFER_SIZE;
+    }
+
+    /* Engineering margin is ten-fold our guess */
+    return 10 * (property_size + worst_write_perf) / worst_write_perf;
+}
+
+/* End copy from system/core/logd/LogBuffer.cpp */
+
+/* dumps the current system state to stdout */
+static void print_header(std::string version) {
+    char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX];
+    char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX];
+    char network[PROPERTY_VALUE_MAX], date[80];
+
+    property_get("ro.build.display.id", build, "(unknown)");
+    property_get("ro.build.fingerprint", fingerprint, "(unknown)");
+    property_get("ro.build.type", build_type, "(unknown)");
+    property_get("ro.baseband", radio, "(unknown)");
+    property_get("ro.bootloader", bootloader, "(unknown)");
+    property_get("gsm.operator.alpha", network, "(unknown)");
+    strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now));
+
+    printf("========================================================\n");
+    printf("== dumpstate: %s\n", date);
+    printf("========================================================\n");
+
+    printf("\n");
+    printf("Build: %s\n", build);
+    printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */
+    printf("Bootloader: %s\n", bootloader);
+    printf("Radio: %s\n", radio);
+    printf("Network: %s\n", network);
+
+    printf("Kernel: ");
+    dump_file(NULL, "/proc/version");
+    printf("Command line: %s\n", strtok(cmdline_buf, "\n"));
+    printf("Bugreport format version: %s\n", version.c_str());
+    printf("Dumpstate info: id=%lu pid=%d\n", id, getpid());
+    printf("\n");
+}
+
+/* adds a new entry to the existing zip file. */
+static bool add_zip_entry_from_fd(const std::string& entry_name, int fd) {
+    if (!zip_writer) {
+        MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n",
+                entry_name.c_str());
+        return false;
+    }
+    // Logging statement  below is useful to time how long each entry takes, but it's too verbose.
+    // MYLOGD("Adding zip entry %s\n", entry_name.c_str());
+    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(),
+            ZipWriter::kCompress, get_mtime(fd, now));
+    if (err) {
+        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
+                ZipWriter::ErrorCodeString(err));
+        return false;
+    }
+
+    std::vector<uint8_t> buffer(65536);
+    while (1) {
+        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer)));
+        if (bytes_read == 0) {
+            break;
+        } else if (bytes_read == -1) {
+            MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno));
+            return false;
+        }
+        err = zip_writer->WriteBytes(buffer.data(), bytes_read);
+        if (err) {
+            MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err));
+            return false;
+        }
+    }
+
+    err = zip_writer->FinishEntry();
+    if (err) {
+        MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
+        return false;
+    }
+
+    return true;
+}
+
+/* adds a new entry to the existing zip file. */
+static bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) {
+    ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC)));
+    if (fd.get() == -1) {
+        MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno));
+        return false;
+    }
+
+    return add_zip_entry_from_fd(entry_name, fd.get());
+}
+
+/* adds a file to the existing zipped bugreport */
+static int _add_file_from_fd(const char *title, const char *path, int fd) {
+    return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1;
+}
+
+/* adds all files from a directory to the zipped bugreport file */
+void add_dir(const char *dir, bool recursive) {
+    if (!zip_writer) {
+        MYLOGD("Not adding dir %s because zip_writer is not set\n", dir);
+        return;
+    }
+    MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive);
+    DurationReporter duration_reporter(dir, NULL);
+    dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd);
+}
+
+/* adds a text entry entry to the existing zip file. */
+static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) {
+    if (!zip_writer) {
+        MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str());
+        return false;
+    }
+    MYLOGD("Adding zip text entry %s\n", entry_name.c_str());
+    int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now);
+    if (err) {
+        MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(),
+                ZipWriter::ErrorCodeString(err));
+        return false;
+    }
+
+    err = zip_writer->WriteBytes(content.c_str(), content.length());
+    if (err) {
+        MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(),
+                ZipWriter::ErrorCodeString(err));
+        return false;
+    }
+
+    err = zip_writer->FinishEntry();
+    if (err) {
+        MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err));
+        return false;
+    }
+
+    return true;
+}
+
+static void dumpstate(const std::string& screenshot_path, const std::string& version) {
+    DurationReporter duration_reporter("DUMPSTATE");
+    unsigned long timeout;
+
+    dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
+    run_command("UPTIME", 10, "uptime", NULL);
+    dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd);
+    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
+    dump_file("MEMORY INFO", "/proc/meminfo");
+    run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL);
+    run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL);
+    dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat");
+    dump_file("VMALLOC INFO", "/proc/vmallocinfo");
+    dump_file("SLAB INFO", "/proc/slabinfo");
+    dump_file("ZONEINFO", "/proc/zoneinfo");
+    dump_file("PAGETYPEINFO", "/proc/pagetypeinfo");
+    dump_file("BUDDYINFO", "/proc/buddyinfo");
+    dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index");
+
+    dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources");
+    dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
+    dump_file("KERNEL SYNC", "/d/sync");
+
+    run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL);
+    run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL);
+
+    run_command("PRINTENV", 10, "printenv", NULL);
+    run_command("NETSTAT", 10, "netstat", "-n", NULL);
+    run_command("LSMOD", 10, "lsmod", NULL);
+
+    do_dmesg();
+
+    run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
+    for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
+    for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
+    for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)");
+
+    if (!screenshot_path.empty()) {
+        MYLOGI("taking late screenshot\n");
+        take_screenshot(screenshot_path);
+        MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
+    }
+
+    // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
+    // calculate timeout
+    timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime",
+                                                        "-v", "printable",
+                                                        "-d",
+                                                        "*:v", NULL);
+    timeout = logcat_timeout("events");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events",
+                                                       "-v", "threadtime",
+                                                       "-v", "printable",
+                                                       "-d",
+                                                       "*:v", NULL);
+    timeout = logcat_timeout("radio");
+    if (timeout < 20000) {
+        timeout = 20000;
+    }
+    run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio",
+                                                       "-v", "threadtime",
+                                                       "-v", "printable",
+                                                       "-d",
+                                                       "*:v", NULL);
+
+    run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL);
+
+    run_command("RAFT LOGS", 600, SU_PATH, "root", "logcompressor", "-r", RAFT_DIR, NULL);
+
+    /* show the traces we collected in main(), if that was done */
+    if (dump_traces_path != NULL) {
+        dump_file("VM TRACES JUST NOW", dump_traces_path);
+    }
+
+    /* only show ANR traces if they're less than 15 minutes old */
+    struct stat st;
+    char anr_traces_path[PATH_MAX];
+    property_get("dalvik.vm.stack-trace-file", anr_traces_path, "");
+    if (!anr_traces_path[0]) {
+        printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n");
+    } else {
+      int fd = TEMP_FAILURE_RETRY(open(anr_traces_path,
+                                       O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK));
+      if (fd < 0) {
+          printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno));
+      } else {
+          dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd);
+      }
+    }
+
+    /* slow traces for slow operations */
+    if (anr_traces_path[0] != 0) {
+        int tail = strlen(anr_traces_path)-1;
+        while (tail > 0 && anr_traces_path[tail] != '/') {
+            tail--;
+        }
+        int i = 0;
+        while (1) {
+            sprintf(anr_traces_path+tail+1, "slow%02d.txt", i);
+            if (stat(anr_traces_path, &st)) {
+                // No traces file at this index, done with the files.
+                break;
+            }
+            dump_file("VM TRACES WHEN SLOW", anr_traces_path);
+            i++;
+        }
+    }
+
+    int dumped = 0;
+    for (size_t i = 0; i < NUM_TOMBSTONES; i++) {
+        if (tombstone_data[i].fd != -1) {
+            const char *name = tombstone_data[i].name;
+            int fd = tombstone_data[i].fd;
+            dumped = 1;
+            if (zip_writer) {
+                if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) {
+                    MYLOGE("Unable to add tombstone %s to zip file\n", name);
+                }
+            } else {
+                dump_file_from_fd("TOMBSTONE", name, fd);
+            }
+            close(fd);
+            tombstone_data[i].fd = -1;
+        }
+    }
+    if (!dumped) {
+        printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR);
+    }
+
+    dump_file("NETWORK DEV INFO", "/proc/net/dev");
+    dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all");
+    dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt");
+    dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl");
+    dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats");
+
+    if (!stat(PSTORE_LAST_KMSG, &st)) {
+        /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */
+        dump_file("LAST KMSG", PSTORE_LAST_KMSG);
+    } else {
+        /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */
+        dump_file("LAST KMSG", "/proc/last_kmsg");
+    }
+
+    /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */
+    run_command("LAST LOGCAT", 10, "logcat", "-L",
+                                             "-b", "all",
+                                             "-v", "threadtime",
+                                             "-v", "printable",
+                                             "-d",
+                                             "*:v", NULL);
+
+    /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */
+
+    run_command("NETWORK INTERFACES", 10, "ip", "link", NULL);
+
+    run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL);
+    run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL);
+
+    run_command("IP RULES", 10, "ip", "rule", "show", NULL);
+    run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL);
+
+    dump_route_tables();
+
+    run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL);
+    run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL);
+
+    run_command("IPTABLES", 10, SU_PATH, "root", "iptables", "-L", "-nvx", NULL);
+    run_command("IP6TABLES", 10, SU_PATH, "root", "ip6tables", "-L", "-nvx", NULL);
+    run_command("IPTABLE NAT", 10, SU_PATH, "root", "iptables", "-t", "nat", "-L", "-nvx", NULL);
+    /* no ip6 nat */
+    run_command("IPTABLE RAW", 10, SU_PATH, "root", "iptables", "-t", "raw", "-L", "-nvx", NULL);
+    run_command("IP6TABLE RAW", 10, SU_PATH, "root", "ip6tables", "-t", "raw", "-L", "-nvx", NULL);
+
+    run_command("WIFI NETWORKS", 20,
+            SU_PATH, "root", "wpa_cli", "IFNAME=wlan0", "list_networks", NULL);
+
+#ifdef FWDUMP_bcmdhd
+    run_command("ND OFFLOAD TABLE", 5,
+            SU_PATH, "root", "wlutil", "nd_hostip", NULL);
+
+    run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20,
+            SU_PATH, "root", "wlutil", "counters", NULL);
+
+    run_command("ND OFFLOAD STATUS (1)", 5,
+            SU_PATH, "root", "wlutil", "nd_status", NULL);
+
+#endif
+    dump_file("INTERRUPTS (1)", "/proc/interrupts");
+
+    run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "connectivity", "--diag", NULL);
+
+#ifdef FWDUMP_bcmdhd
+    run_command("DUMP WIFI STATUS", 20,
+            SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL);
+
+    run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20,
+            SU_PATH, "root", "wlutil", "counters", NULL);
+
+    run_command("ND OFFLOAD STATUS (2)", 5,
+            SU_PATH, "root", "wlutil", "nd_status", NULL);
+#endif
+    dump_file("INTERRUPTS (2)", "/proc/interrupts");
+
+    print_properties();
+
+    run_command("VOLD DUMP", 10, "vdc", "dump", NULL);
+    run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL);
+
+    run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL);
+
+    run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL);
+
+    printf("------ BACKLIGHTS ------\n");
+    printf("LCD brightness=");
+    dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness");
+    printf("Button brightness=");
+    dump_file(NULL, "/sys/class/leds/button-backlight/brightness");
+    printf("Keyboard brightness=");
+    dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness");
+    printf("ALS mode=");
+    dump_file(NULL, "/sys/class/leds/lcd-backlight/als");
+    printf("LCD driver registers:\n");
+    dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
+    printf("\n");
+
+    /* Binder state is expensive to look at as it uses a lot of memory. */
+    dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log");
+    dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log");
+    dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions");
+    dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats");
+    dump_file("BINDER STATE", "/sys/kernel/debug/binder/state");
+
+    printf("========================================================\n");
+    printf("== Board\n");
+    printf("========================================================\n");
+
+    dumpstate_board();
+    printf("\n");
+
+    /* Migrate the ril_dumpstate to a dumpstate_board()? */
+    char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0};
+    property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30");
+    if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) {
+        if (is_user_build()) {
+            // su does not exist on user builds, so try running without it.
+            // This way any implementations of vril-dump that do not require
+            // root can run on user builds.
+            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+                    "vril-dump", NULL);
+        } else {
+            run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout),
+                    SU_PATH, "root", "vril-dump", NULL);
+        }
+    }
+
+    printf("========================================================\n");
+    printf("== Android Framework Services\n");
+    printf("========================================================\n");
+
+    run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo,cpuinfo", NULL);
+
+    printf("========================================================\n");
+    printf("== Checkins\n");
+    printf("========================================================\n");
+
+    run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "batterystats", "-c", NULL);
+    run_command("CHECKIN MEMINFO", 30, "dumpsys", "meminfo", "--checkin", NULL);
+    run_command("CHECKIN NETSTATS", 30, "dumpsys", "netstats", "--checkin", NULL);
+    run_command("CHECKIN PROCSTATS", 30, "dumpsys", "procstats", "-c", NULL);
+    run_command("CHECKIN USAGESTATS", 30, "dumpsys", "usagestats", "-c", NULL);
+    run_command("CHECKIN PACKAGE", 30, "dumpsys", "package", "--checkin", NULL);
+
+    printf("========================================================\n");
+    printf("== Running Application Activities\n");
+    printf("========================================================\n");
+
+    run_command("APP ACTIVITIES", 30, "dumpsys", "activity", "all", NULL);
+
+    printf("========================================================\n");
+    printf("== Running Application Services\n");
+    printf("========================================================\n");
+
+    run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
+
+    printf("========================================================\n");
+    printf("== Running Application Providers\n");
+    printf("========================================================\n");
+
+    run_command("APP SERVICES", 30, "dumpsys", "activity", "provider", "all", NULL);
+
+
+    printf("========================================================\n");
+    printf("== Final progress (pid %d): %d/%d (originally %d)\n",
+            getpid(), progress, weight_total, WEIGHT_TOTAL);
+    printf("========================================================\n");
+    printf("== dumpstate: done\n");
+    printf("========================================================\n");
+}
+
+static void usage() {
+  fprintf(stderr,
+          "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] "
+          "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n"
+          "  -h: display this help message\n"
+          "  -b: play sound file instead of vibrate, at beginning of job\n"
+          "  -e: play sound file instead of vibrate, at end of job\n"
+          "  -o: write to file (instead of stdout)\n"
+          "  -d: append date to filename (requires -o)\n"
+          "  -p: capture screenshot to filename.png (requires -o)\n"
+          "  -z: generate zipped file (requires -o)\n"
+          "  -s: write output to control socket (for init)\n"
+          "  -S: write file location to control socket (for init; requires -o and -z)"
+          "  -q: disable vibrate\n"
+          "  -B: send broadcast when finished (requires -o)\n"
+          "  -P: send broadcast when started and update system properties on "
+          "progress (requires -o and -B)\n"
+          "  -R: take bugreport in remote mode (requires -o, -z, -d and -B, "
+          "shouldn't be used with -P)\n"
+          "  -V: sets the bugreport format version (valid values: %s)\n",
+          VERSION_DEFAULT.c_str());
+}
+
+static void sigpipe_handler(int n) {
+    // don't complain to stderr or stdout
+    _exit(EXIT_FAILURE);
+}
+
+/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the
+   temporary file.
+ */
+static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path,
+        time_t now) {
+    if (!add_zip_entry(bugreport_name, bugreport_path)) {
+        MYLOGE("Failed to add text entry to .zip file\n");
+        return false;
+    }
+    if (!add_text_zip_entry("main_entry.txt", bugreport_name)) {
+        MYLOGE("Failed to add main_entry.txt to .zip file\n");
+        return false;
+    }
+
+    int32_t err = zip_writer->Finish();
+    if (err) {
+        MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err));
+        return false;
+    }
+
+    if (is_user_build()) {
+        MYLOGD("Removing temporary file %s\n", bugreport_path.c_str())
+        if (remove(bugreport_path.c_str())) {
+            ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno));
+        }
+    } else {
+        MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str())
+    }
+
+    return true;
+}
+
+static std::string SHA256_file_hash(std::string filepath) {
+    ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC
+            | O_NOFOLLOW)));
+    if (fd.get() == -1) {
+        MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno));
+        return NULL;
+    }
+
+    SHA256_CTX ctx;
+    SHA256_init(&ctx);
+
+    std::vector<uint8_t> buffer(65536);
+    while (1) {
+        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size()));
+        if (bytes_read == 0) {
+            break;
+        } else if (bytes_read == -1) {
+            MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno));
+            return NULL;
+        }
+
+        SHA256_update(&ctx, buffer.data(), bytes_read);
+    }
+
+    uint8_t hash[SHA256_DIGEST_SIZE];
+    memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE);
+    char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1];
+    for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) {
+        sprintf(hash_buffer + (i * 2), "%02x", hash[i]);
+    }
+    hash_buffer[sizeof(hash_buffer) - 1] = 0;
+    return std::string(hash_buffer);
+}
+
+int main(int argc, char *argv[]) {
+    struct sigaction sigact;
+    int do_add_date = 0;
+    int do_zip_file = 0;
+    int do_vibrate = 1;
+    char* use_outfile = 0;
+    int use_socket = 0;
+    int use_control_socket = 0;
+    int do_fb = 0;
+    int do_broadcast = 0;
+    int do_early_screenshot = 0;
+    int is_remote_mode = 0;
+    std::string version = VERSION_DEFAULT;
+
+    now = time(NULL);
+
+    MYLOGI("begin\n");
+
+    /* gets the sequential id */
+    char last_id[PROPERTY_VALUE_MAX];
+    property_get("dumpstate.last_id", last_id, "0");
+    id = strtoul(last_id, NULL, 10) + 1;
+    sprintf(last_id, "%lu", id);
+    property_set("dumpstate.last_id", last_id);
+    MYLOGI("dumpstate id: %lu\n", id);
+
+    /* clear SIGPIPE handler */
+    memset(&sigact, 0, sizeof(sigact));
+    sigact.sa_handler = sigpipe_handler;
+    sigaction(SIGPIPE, &sigact, NULL);
+
+    /* set as high priority, and protect from OOM killer */
+    setpriority(PRIO_PROCESS, 0, -20);
+    FILE *oom_adj = fopen("/proc/self/oom_adj", "we");
+    if (oom_adj) {
+        fputs("-17", oom_adj);
+        fclose(oom_adj);
+    }
+
+    /* parse arguments */
+    std::string args;
+    format_args(argc, const_cast<const char **>(argv), &args);
+    MYLOGD("Dumpstate command line: %s\n", args.c_str());
+    int c;
+    while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) {
+        switch (c) {
+            case 'd': do_add_date = 1;          break;
+            case 'z': do_zip_file = 1;          break;
+            case 'o': use_outfile = optarg;     break;
+            case 's': use_socket = 1;           break;
+            case 'S': use_control_socket = 1;   break;
+            case 'v': break;  // compatibility no-op
+            case 'q': do_vibrate = 0;           break;
+            case 'p': do_fb = 1;                break;
+            case 'P': do_update_progress = 1;   break;
+            case 'R': is_remote_mode = 1;       break;
+            case 'B': do_broadcast = 1;         break;
+            case 'V': version = optarg;         break;
+            case '?': printf("\n");
+            case 'h':
+                usage();
+                exit(1);
+        }
+    }
+
+    if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) {
+        usage();
+        exit(1);
+    }
+
+    if (use_control_socket && !do_zip_file) {
+        usage();
+        exit(1);
+    }
+
+    if (do_update_progress && !do_broadcast) {
+        usage();
+        exit(1);
+    }
+
+    if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) {
+        usage();
+        exit(1);
+    }
+
+    if (version != VERSION_DEFAULT) {
+      usage();
+      exit(1);
+    }
+
+    MYLOGI("bugreport format version: %s\n", version.c_str());
+
+    do_early_screenshot = do_update_progress;
+
+    // If we are going to use a socket, do it as early as possible
+    // to avoid timeouts from bugreport.
+    if (use_socket) {
+        redirect_to_socket(stdout, "dumpstate");
+    }
+
+    if (use_control_socket) {
+        MYLOGD("Opening control socket\n");
+        control_socket_fd = open_socket("dumpstate");
+    }
+
+    /* full path of the directory where the bugreport files will be written */
+    std::string bugreport_dir;
+
+    /* full path of the temporary file containing the bugreport */
+    std::string tmp_path;
+
+    /* full path of the file containing the dumpstate logs*/
+    std::string log_path;
+
+    /* full path of the systrace file, when enabled */
+    std::string systrace_path;
+
+    /* full path of the temporary file containing the screenshot (when requested) */
+    std::string screenshot_path;
+
+    /* base name (without suffix or extensions) of the bugreport files */
+    std::string base_name;
+
+    /* suffix of the bugreport files - it's typically the date (when invoked with -d),
+     * although it could be changed by the user using a system property */
+    std::string suffix;
+
+    /* pointer to the actual path, be it zip or text */
+    std::string path;
+
+    /* pointer to the zipped file */
+    std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose);
+
+    /* redirect output if needed */
+    bool is_redirecting = !use_socket && use_outfile;
+
+    if (is_redirecting) {
+        bugreport_dir = dirname(use_outfile);
+        base_name = basename(use_outfile);
+        if (do_add_date) {
+            char date[80];
+            strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now));
+            suffix = date;
+        } else {
+            suffix = "undated";
+        }
+        char build_id[PROPERTY_VALUE_MAX];
+        property_get("ro.build.id", build_id, "UNKNOWN_BUILD");
+        base_name = base_name + "-" + build_id;
+        if (do_fb) {
+            // TODO: if dumpstate was an object, the paths could be internal variables and then
+            // we could have a function to calculate the derived values, such as:
+            //     screenshot_path = GetPath(".png");
+            screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png";
+        }
+        tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp";
+        log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-"
+                + std::to_string(getpid()) + ".txt";
+        systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt";
+
+        MYLOGD("Bugreport dir: %s\n"
+                "Base name: %s\n"
+                "Suffix: %s\n"
+                "Log path: %s\n"
+                "Temporary path: %s\n"
+                "Screenshot path: %s\n",
+                bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(),
+                log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str());
+
+        if (do_zip_file) {
+            path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
+            MYLOGD("Creating initial .zip file (%s)\n", path.c_str());
+            create_parent_dirs(path.c_str());
+            zip_file.reset(fopen(path.c_str(), "wb"));
+            if (!zip_file) {
+                MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno));
+                do_zip_file = 0;
+            } else {
+                zip_writer.reset(new ZipWriter(zip_file.get()));
+            }
+            add_text_zip_entry("version.txt", version);
+        }
+
+        if (do_update_progress) {
+            std::vector<std::string> am_args = {
+                 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
+                 "--es", "android.intent.extra.NAME", suffix,
+                 "--ei", "android.intent.extra.ID", std::to_string(id),
+                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
+                 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL),
+            };
+            send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args);
+        }
+    }
+
+    /* read /proc/cmdline before dropping root */
+    FILE *cmdline = fopen("/proc/cmdline", "re");
+    if (cmdline) {
+        fgets(cmdline_buf, sizeof(cmdline_buf), cmdline);
+        fclose(cmdline);
+    }
+
+    /* open the vibrator before dropping root */
+    std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose);
+    if (do_vibrate) {
+        vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we"));
+        if (vibrator) {
+            vibrate(vibrator.get(), 150);
+        }
+    }
+
+    if (do_fb && do_early_screenshot) {
+        if (screenshot_path.empty()) {
+            // should not have happened
+            MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n");
+        } else {
+            MYLOGI("taking early screenshot\n");
+            take_screenshot(screenshot_path);
+            MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str());
+            if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) {
+                MYLOGE("Unable to change ownership of screenshot file %s: %s\n",
+                        screenshot_path.c_str(), strerror(errno));
+            }
+        }
+    }
+
+    if (do_zip_file) {
+        if (chown(path.c_str(), AID_SHELL, AID_SHELL)) {
+            MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno));
+        }
+    }
+
+    if (is_redirecting) {
+        redirect_to_file(stderr, const_cast<char*>(log_path.c_str()));
+        if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) {
+            MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n",
+                    log_path.c_str(), strerror(errno));
+        }
+        /* TODO: rather than generating a text file now and zipping it later,
+           it would be more efficient to redirect stdout to the zip entry
+           directly, but the libziparchive doesn't support that option yet. */
+        redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str()));
+        if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) {
+            MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n",
+                    tmp_path.c_str(), strerror(errno));
+        }
+    }
+    // NOTE: there should be no stdout output until now, otherwise it would break the header.
+    // In particular, DurationReport objects should be created passing 'title, NULL', so their
+    // duration is logged into MYLOG instead.
+    print_header(version);
+
+    // Dumps systrace right away, otherwise it will be filled with unnecessary events.
+    dump_systrace(systrace_path);
+
+    // Invoking the following dumpsys calls before dump_traces() to try and
+    // keep the system stats as close to its initial state as possible.
+    run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL);
+    run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "cpuinfo", "-a", NULL);
+
+    /* collect stack traces from Dalvik and native processes (needs root) */
+    dump_traces_path = dump_traces();
+
+    /* Get the tombstone fds, recovery files, and mount info here while we are running as root. */
+    get_tombstone_fds(tombstone_data);
+    add_dir(RECOVERY_DIR, true);
+    add_dir(RECOVERY_DATA_DIR, true);
+    add_dir(LOGPERSIST_DATA_DIR, false);
+    add_mountinfo();
+
+    if (!drop_root_user()) {
+        return -1;
+    }
+
+    dumpstate(do_early_screenshot ? "": screenshot_path, version);
+
+    /* close output if needed */
+    if (is_redirecting) {
+        fclose(stdout);
+    }
+
+    /* rename or zip the (now complete) .tmp file to its final location */
+    if (use_outfile) {
+
+        /* check if user changed the suffix using system properties */
+        char key[PROPERTY_KEY_MAX];
+        char value[PROPERTY_VALUE_MAX];
+        sprintf(key, "dumpstate.%d.name", getpid());
+        property_get(key, value, "");
+        bool change_suffix= false;
+        if (value[0]) {
+            /* must whitelist which characters are allowed, otherwise it could cross directories */
+            std::regex valid_regex("^[-_a-zA-Z0-9]+$");
+            if (std::regex_match(value, valid_regex)) {
+                change_suffix = true;
+            } else {
+                MYLOGE("invalid suffix provided by user: %s\n", value);
+            }
+        }
+        if (change_suffix) {
+            MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value);
+            suffix = value;
+            if (!screenshot_path.empty()) {
+                std::string new_screenshot_path =
+                        bugreport_dir + "/" + base_name + "-" + suffix + ".png";
+                if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) {
+                    MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(),
+                            new_screenshot_path.c_str(), strerror(errno));
+                } else {
+                    screenshot_path = new_screenshot_path;
+                }
+            }
+        }
+
+        bool do_text_file = true;
+        if (do_zip_file) {
+            std::string entry_name = base_name + "-" + suffix + ".txt";
+            MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str());
+            if (!finish_zip_file(entry_name, tmp_path, now)) {
+                MYLOGE("Failed to finish zip file; sending text bugreport instead\n");
+                do_text_file = true;
+            } else {
+                do_text_file = false;
+                // Since zip file is already created, it needs to be renamed.
+                std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip";
+                if (path != new_path) {
+                    MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str());
+                    if (rename(path.c_str(), new_path.c_str())) {
+                        MYLOGE("rename(%s, %s): %s\n", path.c_str(),
+                                new_path.c_str(), strerror(errno));
+                    } else {
+                        path = new_path;
+                    }
+                }
+            }
+        }
+        if (do_text_file) {
+            path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt";
+            MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str());
+            if (rename(tmp_path.c_str(), path.c_str())) {
+                MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno));
+                path.clear();
+            }
+        }
+        if (use_control_socket) {
+            if (do_text_file) {
+                dprintf(control_socket_fd, "FAIL:could not create zip file, check %s "
+                        "for more details\n", log_path.c_str());
+            } else {
+                dprintf(control_socket_fd, "OK:%s\n", path.c_str());
+            }
+        }
+    }
+
+    /* vibrate a few but shortly times to let user know it's finished */
+    if (vibrator) {
+        for (int i = 0; i < 3; i++) {
+            vibrate(vibrator.get(), 75);
+            usleep((75 + 50) * 1000);
+        }
+    }
+
+    /* tell activity manager we're done */
+    if (do_broadcast) {
+        if (!path.empty()) {
+            MYLOGI("Final bugreport path: %s\n", path.c_str());
+            std::vector<std::string> am_args = {
+                 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground",
+                 "--ei", "android.intent.extra.ID", std::to_string(id),
+                 "--ei", "android.intent.extra.PID", std::to_string(getpid()),
+                 "--ei", "android.intent.extra.MAX", std::to_string(weight_total),
+                 "--es", "android.intent.extra.BUGREPORT", path,
+                 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path
+            };
+            if (do_fb) {
+                am_args.push_back("--es");
+                am_args.push_back("android.intent.extra.SCREENSHOT");
+                am_args.push_back(screenshot_path);
+            }
+            if (is_remote_mode) {
+                am_args.push_back("--es");
+                am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH");
+                am_args.push_back(SHA256_file_hash(path));
+                send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args);
+            } else {
+                send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args);
+            }
+        } else {
+            MYLOGE("Skipping finished broadcast because bugreport could not be generated\n");
+        }
+    }
+
+    MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL);
+    MYLOGI("done\n");
+
+    if (is_redirecting) {
+        fclose(stderr);
+    }
+
+    if (use_control_socket && control_socket_fd >= 0) {
+        MYLOGD("Closing control socket\n");
+        close(control_socket_fd);
+    }
+
+    return 0;
+}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index c5d3044..c51c79a 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -17,19 +17,76 @@
 #ifndef _DUMPSTATE_H_
 #define _DUMPSTATE_H_
 
+/* When defined, skips the real dumps and just print the section headers.
+   Useful when debugging dumpstate itself. */
+//#define _DUMPSTATE_DRY_RUN_
+
+#ifdef _DUMPSTATE_DRY_RUN_
+#define ON_DRY_RUN_RETURN(X) return X
+#define ON_DRY_RUN(code) code
+#else
+#define ON_DRY_RUN_RETURN(X)
+#define ON_DRY_RUN(code)
+#endif
+
+#ifndef MYLOGD
+#define MYLOGD(...) fprintf(stderr, __VA_ARGS__); ALOGD(__VA_ARGS__);
+#endif
+
+#ifndef MYLOGI
+#define MYLOGI(...) fprintf(stderr, __VA_ARGS__); ALOGI(__VA_ARGS__);
+#endif
+
+#ifndef MYLOGE
+#define MYLOGE(...) fprintf(stderr, __VA_ARGS__); ALOGE(__VA_ARGS__);
+#endif
+
 #include <time.h>
 #include <unistd.h>
 #include <stdbool.h>
 #include <stdio.h>
+#include <vector>
 
 #define SU_PATH "/system/xbin/su"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef void (for_each_pid_func)(int, const char *);
 typedef void (for_each_tid_func)(int, int, const char *);
 
+/* Estimated total weight of bugreport generation.
+ *
+ * Each section contributes to the total weight by an individual weight, so the overall progress
+ * can be calculated by dividing the all completed weight by the total weight.
+ *
+ * This value is defined empirically and it need to be adjusted as more sections are added.
+ *
+ * It does not need to match the exact sum of all sections, but ideally it should to be slight more
+ * than such sum: a value too high will cause the bugreport to finish before the user expected (for
+ * example, jumping from 70% to 100%), while a value too low will cause the progress to get stuck
+ * at an almost-finished value (like 99%) for a while.
+ */
+static const int WEIGHT_TOTAL = 6500;
+
+/* Most simple commands have 10 as timeout, so 5 is a good estimate */
+static const int WEIGHT_FILE = 5;
+
+/*
+ * TODO: the dumpstate internal state is getting fragile; for example, this variable is defined
+ * here, declared at utils.cpp, and used on utils.cpp and dumpstate.cpp.
+ * It would be better to take advantage of the C++ migration and encapsulate the state in an object,
+ * but that will be better handled in a major C++ refactoring, which would also get rid of other C
+ * idioms (like using std::string instead of char*, removing varargs, etc...) */
+extern int do_update_progress, progress, weight_total;
+
 /* prints the contents of a file */
 int dump_file(const char *title, const char *path);
 
+/* saves the the contents of a file as a long */
+int read_file_as_long(const char *path, long int *output);
+
 /* prints the contents of the fd
  * fd must have been opened with the flag O_NONBLOCK.
  */
@@ -45,18 +102,46 @@
         bool (*skip)(const char *path),
         int (*dump_from_fd)(const char *title, const char *path, int fd));
 
+// TODO: need to refactor all those run_command variations; there shold be just one, receiving an
+// optional CommandOptions objects with values such as run_always, drop_root, etc...
+
 /* forks a command and waits for it to finish -- terminate args with NULL */
+int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...);
 int run_command(const char *title, int timeout_seconds, const char *command, ...);
 
+enum RootMode { DROP_ROOT, DONT_DROP_ROOT };
+enum StdoutMode { NORMAL_STDOUT, REDIRECT_TO_STDERR };
+
+/* forks a command and waits for it to finish
+   first element of args is the command, and last must be NULL.
+   command is always ran, even when _DUMPSTATE_DRY_RUN_ is defined. */
+int run_command_always(const char *title, RootMode root_mode, StdoutMode stdout_mode,
+        int timeout_seconds, const char *args[]);
+
+/* switch to non-root user and group */
+bool drop_root_user();
+
+/* sends a broadcast using Activity Manager */
+void send_broadcast(const std::string& action, const std::vector<std::string>& args);
+
+/* updates the overall progress of dumpstate by the given weight increment */
+void update_progress(int weight);
+
 /* prints all the system properties */
 void print_properties();
 
+/** opens a socket and returns its file descriptor */
+int open_socket(const char *service);
+
 /* redirect output to a service control socket */
 void redirect_to_socket(FILE *redirect, const char *service);
 
 /* redirect output to a file */
 void redirect_to_file(FILE *redirect, char *path);
 
+/* create leading directories, if necessary */
+void create_parent_dirs(const char *path);
+
 /* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
 const char *dump_traces();
 
@@ -69,6 +154,9 @@
 /* Displays a blocked processes in-kernel wait channel */
 void show_wchan(int pid, int tid, const char *name);
 
+/* Displays a processes times */
+void show_showtime(int pid, const char *name);
+
 /* Runs "showmap" for a process */
 void do_showmap(int pid, const char *name);
 
@@ -84,4 +172,49 @@
 /* Implemented by libdumpstate_board to dump board-specific info */
 void dumpstate_board();
 
+/* Takes a screenshot and save it to the given file */
+void take_screenshot(const std::string& path);
+
+/* Vibrates for a given durating (in milliseconds). */
+void vibrate(FILE* vibrator, int ms);
+
+/* Checks if a given path is a directory. */
+bool is_dir(const char* pathname);
+
+/** Gets the last modification time of a file, or default time if file is not found. */
+time_t get_mtime(int fd, time_t default_mtime);
+
+/* dump eMMC Extended CSD data */
+void dump_emmc_ecsd(const char *ext_csd_path);
+
+/** gets command-line arguments */
+void format_args(int argc, const char *argv[], std::string *args);
+
+/*
+ * Helper class used to report how long it takes for a section to finish.
+ *
+ * Typical usage:
+ *
+ *    DurationReporter duration_reporter(title);
+ *
+ */
+class DurationReporter {
+public:
+    DurationReporter(const char *title);
+    DurationReporter(const char *title, FILE* out);
+
+    ~DurationReporter();
+
+    static uint64_t nanotime();
+
+private:
+    const char* title_;
+    FILE* out_;
+    uint64_t started_;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _DUMPSTATE_H_ */
diff --git a/cmds/dumpstate/dumpstate.rc b/cmds/dumpstate/dumpstate.rc
new file mode 100644
index 0000000..1f56d21
--- /dev/null
+++ b/cmds/dumpstate/dumpstate.rc
@@ -0,0 +1,40 @@
+on boot
+    # Allow bugreports access to eMMC 5.0 stats
+    chown root mount /sys/kernel/debug/mmc0/mmc0:0001/ext_csd
+    chmod 0440 /sys/kernel/debug/mmc0/mmc0:0001/ext_csd
+
+service dumpstate /system/bin/dumpstate -s
+    class main
+    socket dumpstate stream 0660 shell log
+    disabled
+    oneshot
+
+# dumpstatez generates a zipped bugreport but also uses a socket to print the file location once
+# it is finished.
+service dumpstatez /system/bin/dumpstate -S -d -z \
+        -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+    socket dumpstate stream 0660 shell log
+    class main
+    disabled
+    oneshot
+
+# bugreportplus is an enhanced version of bugreport that provides a better
+# user interface (like displaying progress and allowing user to enter details).
+# It's typically triggered by the power button or developer settings.
+service bugreportplus /system/bin/dumpstate -d -B -P -z \
+        -o /data/user_de/0/com.android.shell/files/bugreports/bugreport
+    class main
+    disabled
+    oneshot
+
+# bugreportremote is an altered version of bugreport that is supposed to be
+# called not by human user of the device, but by DevicePolicyManagerService only when the
+# Device Owner explicitly requests it, and shared with the Device Policy Controller (DPC) app only
+# if the user consents
+# it will disable vibrations, screenshot taking and will not track progress or
+# allow user to enter any details
+service bugreportremote /system/bin/dumpstate -d -q -B -R -z \
+        -o /data/user_de/0/com.android.shell/files/bugreports/remote/bugreport
+    class main
+    disabled
+    oneshot
diff --git a/cmds/dumpstate/libdumpstate_default.c b/cmds/dumpstate/libdumpstate_default.cpp
similarity index 100%
rename from cmds/dumpstate/libdumpstate_default.c
rename to cmds/dumpstate/libdumpstate_default.cpp
diff --git a/cmds/dumpstate/utils.c b/cmds/dumpstate/utils.c
deleted file mode 100644
index d679787..0000000
--- a/cmds/dumpstate/utils.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * 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 <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/inotify.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <sys/klog.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/prctl.h>
-
-#include <cutils/debugger.h>
-#include <cutils/properties.h>
-#include <cutils/sockets.h>
-#include <private/android_filesystem_config.h>
-
-#include <selinux/android.h>
-
-#include "dumpstate.h"
-
-static const int64_t NANOS_PER_SEC = 1000000000;
-
-/* list of native processes to include in the native dumps */
-static const char* native_processes_to_dump[] = {
-        "/system/bin/drmserver",
-        "/system/bin/mediaserver",
-        "/system/bin/sdcard",
-        "/system/bin/surfaceflinger",
-        NULL,
-};
-
-static uint64_t nanotime() {
-    struct timespec ts;
-    clock_gettime(CLOCK_MONOTONIC, &ts);
-    return (uint64_t)ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
-}
-
-void for_each_userid(void (*func)(int), const char *header) {
-    DIR *d;
-    struct dirent *de;
-
-    if (header) printf("\n------ %s ------\n", header);
-    func(0);
-
-    if (!(d = opendir("/data/system/users"))) {
-        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
-        return;
-    }
-
-    while ((de = readdir(d))) {
-        int userid;
-        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
-            continue;
-        }
-        func(userid);
-    }
-
-    closedir(d);
-}
-
-static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
-    DIR *d;
-    struct dirent *de;
-
-    if (!(d = opendir("/proc"))) {
-        printf("Failed to open /proc (%s)\n", strerror(errno));
-        return;
-    }
-
-    printf("\n------ %s ------\n", header);
-    while ((de = readdir(d))) {
-        int pid;
-        int fd;
-        char cmdpath[255];
-        char cmdline[255];
-
-        if (!(pid = atoi(de->d_name))) {
-            continue;
-        }
-
-        sprintf(cmdpath,"/proc/%d/cmdline", pid);
-        memset(cmdline, 0, sizeof(cmdline));
-        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) < 0) {
-            strcpy(cmdline, "N/A");
-        } else {
-            read(fd, cmdline, sizeof(cmdline) - 1);
-            close(fd);
-        }
-        helper(pid, cmdline, arg);
-    }
-
-    closedir(d);
-}
-
-static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
-    for_each_pid_func *func = arg;
-    func(pid, cmdline);
-}
-
-void for_each_pid(for_each_pid_func func, const char *header) {
-    __for_each_pid(for_each_pid_helper, header, func);
-}
-
-static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
-    DIR *d;
-    struct dirent *de;
-    char taskpath[255];
-    for_each_tid_func *func = arg;
-
-    sprintf(taskpath, "/proc/%d/task", pid);
-
-    if (!(d = opendir(taskpath))) {
-        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
-        return;
-    }
-
-    func(pid, pid, cmdline);
-
-    while ((de = readdir(d))) {
-        int tid;
-        int fd;
-        char commpath[255];
-        char comm[255];
-
-        if (!(tid = atoi(de->d_name))) {
-            continue;
-        }
-
-        if (tid == pid)
-            continue;
-
-        sprintf(commpath,"/proc/%d/comm", tid);
-        memset(comm, 0, sizeof(comm));
-        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
-            strcpy(comm, "N/A");
-        } else {
-            char *c;
-            read(fd, comm, sizeof(comm) - 1);
-            close(fd);
-
-            c = strrchr(comm, '\n');
-            if (c) {
-                *c = '\0';
-            }
-        }
-        func(pid, tid, comm);
-    }
-
-    closedir(d);
-}
-
-void for_each_tid(for_each_tid_func func, const char *header) {
-    __for_each_pid(for_each_tid_helper, header, func);
-}
-
-void show_wchan(int pid, int tid, const char *name) {
-    char path[255];
-    char buffer[255];
-    int fd;
-    char name_buffer[255];
-
-    memset(buffer, 0, sizeof(buffer));
-
-    sprintf(path, "/proc/%d/wchan", tid);
-    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
-        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
-        return;
-    }
-
-    if (read(fd, buffer, sizeof(buffer)) < 0) {
-        printf("Failed to read '%s' (%s)\n", path, strerror(errno));
-        goto out_close;
-    }
-
-    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
-             pid == tid ? 0 : 3, "", name);
-
-    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
-
-out_close:
-    close(fd);
-    return;
-}
-
-void do_dmesg() {
-    printf("------ KERNEL LOG (dmesg) ------\n");
-    /* Get size of kernel buffer */
-    int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
-    if (size <= 0) {
-        printf("Unexpected klogctl return value: %d\n\n", size);
-        return;
-    }
-    char *buf = (char *) malloc(size + 1);
-    if (buf == NULL) {
-        printf("memory allocation failed\n\n");
-        return;
-    }
-    int retval = klogctl(KLOG_READ_ALL, buf, size);
-    if (retval < 0) {
-        printf("klogctl failure\n\n");
-        free(buf);
-        return;
-    }
-    buf[retval] = '\0';
-    printf("%s\n\n", buf);
-    free(buf);
-    return;
-}
-
-void do_showmap(int pid, const char *name) {
-    char title[255];
-    char arg[255];
-
-    sprintf(title, "SHOW MAP %d (%s)", pid, name);
-    sprintf(arg, "%d", pid);
-    run_command(title, 10, SU_PATH, "root", "showmap", arg, NULL);
-}
-
-static int _dump_file_from_fd(const char *title, const char *path, int fd) {
-    if (title) printf("------ %s (%s", title, path);
-
-    if (title) {
-        struct stat st;
-        if (memcmp(path, "/proc/", 6) && memcmp(path, "/sys/", 5) && !fstat(fd, &st)) {
-            char stamp[80];
-            time_t mtime = st.st_mtime;
-            strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime));
-            printf(": %s", stamp);
-        }
-        printf(") ------\n");
-    }
-
-    bool newline = false;
-    fd_set read_set;
-    struct timeval tm;
-    while (1) {
-        FD_ZERO(&read_set);
-        FD_SET(fd, &read_set);
-        /* Timeout if no data is read for 30 seconds. */
-        tm.tv_sec = 30;
-        tm.tv_usec = 0;
-        uint64_t elapsed = nanotime();
-        int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm));
-        if (ret == -1) {
-            printf("*** %s: select failed: %s\n", path, strerror(errno));
-            newline = true;
-            break;
-        } else if (ret == 0) {
-            elapsed = nanotime() - elapsed;
-            printf("*** %s: Timed out after %.3fs\n", path,
-                   (float) elapsed / NANOS_PER_SEC);
-            newline = true;
-            break;
-        } else {
-            char buffer[65536];
-            ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
-            if (bytes_read > 0) {
-                fwrite(buffer, bytes_read, 1, stdout);
-                newline = (buffer[bytes_read-1] == '\n');
-            } else {
-                if (bytes_read == -1) {
-                    printf("*** %s: Failed to read from fd: %s", path, strerror(errno));
-                    newline = true;
-                }
-                break;
-            }
-        }
-    }
-    close(fd);
-
-    if (!newline) printf("\n");
-    if (title) printf("\n");
-    return 0;
-}
-
-/* prints the contents of a file */
-int dump_file(const char *title, const char *path) {
-    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
-    if (fd < 0) {
-        int err = errno;
-        if (title) printf("------ %s (%s) ------\n", title, path);
-        printf("*** %s: %s\n", path, strerror(err));
-        if (title) printf("\n");
-        return -1;
-    }
-    return _dump_file_from_fd(title, path, fd);
-}
-
-/* calls skip to gate calling dump_from_fd recursively
- * in the specified directory. dump_from_fd defaults to
- * dump_file_from_fd above when set to NULL. skip defaults
- * to false when set to NULL. dump_from_fd will always be
- * called with title NULL.
- */
-int dump_files(const char *title, const char *dir,
-        bool (*skip)(const char *path),
-        int (*dump_from_fd)(const char *title, const char *path, int fd)) {
-    DIR *dirp;
-    struct dirent *d;
-    char *newpath = NULL;
-    char *slash = "/";
-    int fd, retval = 0;
-
-    if (title) {
-        printf("------ %s (%s) ------\n", title, dir);
-    }
-
-    if (dir[strlen(dir) - 1] == '/') {
-        ++slash;
-    }
-    dirp = opendir(dir);
-    if (dirp == NULL) {
-        retval = -errno;
-        fprintf(stderr, "%s: %s\n", dir, strerror(errno));
-        return retval;
-    }
-
-    if (!dump_from_fd) {
-        dump_from_fd = dump_file_from_fd;
-    }
-    for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
-        if ((d->d_name[0] == '.')
-         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
-          || (d->d_name[1] == '\0'))) {
-            continue;
-        }
-        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
-                 (d->d_type == DT_DIR) ? "/" : "");
-        if (!newpath) {
-            retval = -errno;
-            continue;
-        }
-        if (skip && (*skip)(newpath)) {
-            continue;
-        }
-        if (d->d_type == DT_DIR) {
-            int ret = dump_files(NULL, newpath, skip, dump_from_fd);
-            if (ret < 0) {
-                retval = ret;
-            }
-            continue;
-        }
-        fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
-        if (fd < 0) {
-            retval = fd;
-            printf("*** %s: %s\n", newpath, strerror(errno));
-            continue;
-        }
-        (*dump_from_fd)(NULL, newpath, fd);
-    }
-    closedir(dirp);
-    if (title) {
-        printf("\n");
-    }
-    return retval;
-}
-
-/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
- * it's possible to avoid issues where opening the file itself can get
- * stuck.
- */
-int dump_file_from_fd(const char *title, const char *path, int fd) {
-    int flags = fcntl(fd, F_GETFL);
-    if (flags == -1) {
-        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
-        return -1;
-    } else if (!(flags & O_NONBLOCK)) {
-        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
-        return -1;
-    }
-    return _dump_file_from_fd(title, path, fd);
-}
-
-bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
-    sigset_t child_mask, old_mask;
-    sigemptyset(&child_mask);
-    sigaddset(&child_mask, SIGCHLD);
-
-    if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
-        printf("*** sigprocmask failed: %s\n", strerror(errno));
-        return false;
-    }
-
-    struct timespec ts;
-    ts.tv_sec = timeout_seconds;
-    ts.tv_nsec = 0;
-    int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
-    int saved_errno = errno;
-    // Set the signals back the way they were.
-    if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
-        printf("*** sigprocmask failed: %s\n", strerror(errno));
-        if (ret == 0) {
-            return false;
-        }
-    }
-    if (ret == -1) {
-        errno = saved_errno;
-        if (errno == EAGAIN) {
-            errno = ETIMEDOUT;
-        } else {
-            printf("*** sigtimedwait failed: %s\n", strerror(errno));
-        }
-        return false;
-    }
-
-    pid_t child_pid = waitpid(pid, status, WNOHANG);
-    if (child_pid != pid) {
-        if (child_pid != -1) {
-            printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
-        } else {
-            printf("*** waitpid failed: %s\n", strerror(errno));
-        }
-        return false;
-    }
-    return true;
-}
-
-/* forks a command and waits for it to finish */
-int run_command(const char *title, int timeout_seconds, const char *command, ...) {
-    fflush(stdout);
-    uint64_t start = nanotime();
-    pid_t pid = fork();
-
-    /* handle error case */
-    if (pid < 0) {
-        printf("*** fork: %s\n", strerror(errno));
-        return pid;
-    }
-
-    /* handle child case */
-    if (pid == 0) {
-        const char *args[1024] = {command};
-        size_t arg;
-
-        /* make sure the child dies when dumpstate dies */
-        prctl(PR_SET_PDEATHSIG, SIGKILL);
-
-        /* just ignore SIGPIPE, will go down with parent's */
-        struct sigaction sigact;
-        memset(&sigact, 0, sizeof(sigact));
-        sigact.sa_handler = SIG_IGN;
-        sigaction(SIGPIPE, &sigact, NULL);
-
-        va_list ap;
-        va_start(ap, command);
-        if (title) printf("------ %s (%s", title, command);
-        for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
-            args[arg] = va_arg(ap, const char *);
-            if (args[arg] == NULL) break;
-            if (title) printf(" %s", args[arg]);
-        }
-        if (title) printf(") ------\n");
-        fflush(stdout);
-
-        execvp(command, (char**) args);
-        printf("*** exec(%s): %s\n", command, strerror(errno));
-        fflush(stdout);
-        _exit(-1);
-    }
-
-    /* handle parent case */
-    int status;
-    bool ret = waitpid_with_timeout(pid, timeout_seconds, &status);
-    uint64_t elapsed = nanotime() - start;
-    if (!ret) {
-        if (errno == ETIMEDOUT) {
-            printf("*** %s: Timed out after %.3fs (killing pid %d)\n", command,
-                   (float) elapsed / NANOS_PER_SEC, pid);
-        } else {
-            printf("*** %s: Error after %.4fs (killing pid %d)\n", command,
-                   (float) elapsed / NANOS_PER_SEC, pid);
-        }
-        kill(pid, SIGTERM);
-        if (!waitpid_with_timeout(pid, 5, NULL)) {
-            kill(pid, SIGKILL);
-            if (!waitpid_with_timeout(pid, 5, NULL)) {
-                printf("*** %s: Cannot kill %d even with SIGKILL.\n", command, pid);
-            }
-        }
-        return -1;
-    }
-
-    if (WIFSIGNALED(status)) {
-        printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
-    } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
-        printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
-    }
-    if (title) printf("[%s: %.3fs elapsed]\n\n", command, (float)elapsed / NANOS_PER_SEC);
-
-    return status;
-}
-
-size_t num_props = 0;
-static char* props[2000];
-
-static void print_prop(const char *key, const char *name, void *user) {
-    (void) user;
-    if (num_props < sizeof(props) / sizeof(props[0])) {
-        char buf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 10];
-        snprintf(buf, sizeof(buf), "[%s]: [%s]\n", key, name);
-        props[num_props++] = strdup(buf);
-    }
-}
-
-static int compare_prop(const void *a, const void *b) {
-    return strcmp(*(char * const *) a, *(char * const *) b);
-}
-
-/* prints all the system properties */
-void print_properties() {
-    size_t i;
-    num_props = 0;
-    property_list(print_prop, NULL);
-    qsort(&props, num_props, sizeof(props[0]), compare_prop);
-
-    printf("------ SYSTEM PROPERTIES ------\n");
-    for (i = 0; i < num_props; ++i) {
-        fputs(props[i], stdout);
-        free(props[i]);
-    }
-    printf("\n");
-}
-
-/* redirect output to a service control socket */
-void redirect_to_socket(FILE *redirect, const char *service) {
-    int s = android_get_control_socket(service);
-    if (s < 0) {
-        fprintf(stderr, "android_get_control_socket(%s): %s\n", service, strerror(errno));
-        exit(1);
-    }
-    fcntl(s, F_SETFD, FD_CLOEXEC);
-    if (listen(s, 4) < 0) {
-        fprintf(stderr, "listen(control socket): %s\n", strerror(errno));
-        exit(1);
-    }
-
-    struct sockaddr addr;
-    socklen_t alen = sizeof(addr);
-    int fd = accept(s, &addr, &alen);
-    if (fd < 0) {
-        fprintf(stderr, "accept(control socket): %s\n", strerror(errno));
-        exit(1);
-    }
-
-    fflush(redirect);
-    dup2(fd, fileno(redirect));
-    close(fd);
-}
-
-/* redirect output to a file */
-void redirect_to_file(FILE *redirect, char *path) {
-    char *chp = path;
-
-    /* skip initial slash */
-    if (chp[0] == '/')
-        chp++;
-
-    /* create leading directories, if necessary */
-    while (chp && chp[0]) {
-        chp = strchr(chp, '/');
-        if (chp) {
-            *chp = 0;
-            mkdir(path, 0770);  /* drwxrwx--- */
-            *chp++ = '/';
-        }
-    }
-
-    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
-                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
-    if (fd < 0) {
-        fprintf(stderr, "%s: %s\n", path, strerror(errno));
-        exit(1);
-    }
-
-    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
-    close(fd);
-}
-
-static bool should_dump_native_traces(const char* path) {
-    for (const char** p = native_processes_to_dump; *p; p++) {
-        if (!strcmp(*p, path)) {
-            return true;
-        }
-    }
-    return false;
-}
-
-/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
-const char *dump_traces() {
-    const char* result = NULL;
-
-    char traces_path[PROPERTY_VALUE_MAX] = "";
-    property_get("dalvik.vm.stack-trace-file", traces_path, "");
-    if (!traces_path[0]) return NULL;
-
-    /* move the old traces.txt (if any) out of the way temporarily */
-    char anr_traces_path[PATH_MAX];
-    strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
-    strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
-    if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
-        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
-        return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
-    }
-
-    /* make the directory if necessary */
-    char anr_traces_dir[PATH_MAX];
-    strlcpy(anr_traces_dir, traces_path, sizeof(anr_traces_dir));
-    char *slash = strrchr(anr_traces_dir, '/');
-    if (slash != NULL) {
-        *slash = '\0';
-        if (!mkdir(anr_traces_dir, 0775)) {
-            chown(anr_traces_dir, AID_SYSTEM, AID_SYSTEM);
-            chmod(anr_traces_dir, 0775);
-            if (selinux_android_restorecon(anr_traces_dir, 0) == -1) {
-                fprintf(stderr, "restorecon failed for %s: %s\n", anr_traces_dir, strerror(errno));
-            }
-        } else if (errno != EEXIST) {
-            fprintf(stderr, "mkdir(%s): %s\n", anr_traces_dir, strerror(errno));
-            return NULL;
-        }
-    }
-
-    /* create a new, empty traces.txt file to receive stack dumps */
-    int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
-                                     0666));  /* -rw-rw-rw- */
-    if (fd < 0) {
-        fprintf(stderr, "%s: %s\n", traces_path, strerror(errno));
-        return NULL;
-    }
-    int chmod_ret = fchmod(fd, 0666);
-    if (chmod_ret < 0) {
-        fprintf(stderr, "fchmod on %s failed: %s\n", traces_path, strerror(errno));
-        close(fd);
-        return NULL;
-    }
-
-    /* walk /proc and kill -QUIT all Dalvik processes */
-    DIR *proc = opendir("/proc");
-    if (proc == NULL) {
-        fprintf(stderr, "/proc: %s\n", strerror(errno));
-        goto error_close_fd;
-    }
-
-    /* use inotify to find when processes are done dumping */
-    int ifd = inotify_init();
-    if (ifd < 0) {
-        fprintf(stderr, "inotify_init: %s\n", strerror(errno));
-        goto error_close_fd;
-    }
-
-    int wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
-    if (wfd < 0) {
-        fprintf(stderr, "inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
-        goto error_close_ifd;
-    }
-
-    struct dirent *d;
-    int dalvik_found = 0;
-    while ((d = readdir(proc))) {
-        int pid = atoi(d->d_name);
-        if (pid <= 0) continue;
-
-        char path[PATH_MAX];
-        char data[PATH_MAX];
-        snprintf(path, sizeof(path), "/proc/%d/exe", pid);
-        ssize_t len = readlink(path, data, sizeof(data) - 1);
-        if (len <= 0) {
-            continue;
-        }
-        data[len] = '\0';
-
-        if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
-            /* skip zygote -- it won't dump its stack anyway */
-            snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
-            int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
-            len = read(cfd, data, sizeof(data) - 1);
-            close(cfd);
-            if (len <= 0) {
-                continue;
-            }
-            data[len] = '\0';
-            if (!strncmp(data, "zygote", strlen("zygote"))) {
-                continue;
-            }
-
-            ++dalvik_found;
-            uint64_t start = nanotime();
-            if (kill(pid, SIGQUIT)) {
-                fprintf(stderr, "kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
-                continue;
-            }
-
-            /* wait for the writable-close notification from inotify */
-            struct pollfd pfd = { ifd, POLLIN, 0 };
-            int ret = poll(&pfd, 1, 5000);  /* 5 sec timeout */
-            if (ret < 0) {
-                fprintf(stderr, "poll: %s\n", strerror(errno));
-            } else if (ret == 0) {
-                fprintf(stderr, "warning: timed out dumping pid %d\n", pid);
-            } else {
-                struct inotify_event ie;
-                read(ifd, &ie, sizeof(ie));
-            }
-
-            if (lseek(fd, 0, SEEK_END) < 0) {
-                fprintf(stderr, "lseek: %s\n", strerror(errno));
-            } else {
-                dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n",
-                        pid, (float)(nanotime() - start) / NANOS_PER_SEC);
-            }
-        } else if (should_dump_native_traces(data)) {
-            /* dump native process if appropriate */
-            if (lseek(fd, 0, SEEK_END) < 0) {
-                fprintf(stderr, "lseek: %s\n", strerror(errno));
-            } else {
-                static uint16_t timeout_failures = 0;
-                uint64_t start = nanotime();
-
-                /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
-                if (timeout_failures == 3) {
-                    dprintf(fd, "too many stack dump failures, skipping...\n");
-                } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
-                    dprintf(fd, "dumping failed, likely due to a timeout\n");
-                    timeout_failures++;
-                } else {
-                    timeout_failures = 0;
-                }
-                dprintf(fd, "[dump native stack %d: %.3fs elapsed]\n",
-                        pid, (float)(nanotime() - start) / NANOS_PER_SEC);
-            }
-        }
-    }
-
-    if (dalvik_found == 0) {
-        fprintf(stderr, "Warning: no Dalvik processes found to dump stacks\n");
-    }
-
-    static char dump_traces_path[PATH_MAX];
-    strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
-    strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
-    if (rename(traces_path, dump_traces_path)) {
-        fprintf(stderr, "rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
-        goto error_close_ifd;
-    }
-    result = dump_traces_path;
-
-    /* replace the saved [ANR] traces.txt file */
-    rename(anr_traces_path, traces_path);
-
-error_close_ifd:
-    close(ifd);
-error_close_fd:
-    close(fd);
-    return result;
-}
-
-void dump_route_tables() {
-    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
-    dump_file("RT_TABLES", RT_TABLES_PATH);
-    FILE* fp = fopen(RT_TABLES_PATH, "re");
-    if (!fp) {
-        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
-        return;
-    }
-    char table[16];
-    // Each line has an integer (the table number), a space, and a string (the table name). We only
-    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
-    // Add a fixed max limit so this doesn't go awry.
-    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
-        run_command("ROUTE TABLE IPv4", 10, "ip", "-4", "route", "show", "table", table, NULL);
-        run_command("ROUTE TABLE IPv6", 10, "ip", "-6", "route", "show", "table", table, NULL);
-    }
-    fclose(fp);
-}
diff --git a/cmds/dumpstate/utils.cpp b/cmds/dumpstate/utils.cpp
new file mode 100644
index 0000000..f1a1ed6
--- /dev/null
+++ b/cmds/dumpstate/utils.cpp
@@ -0,0 +1,1390 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * 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 <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <string.h>
+#include <sys/capability.h>
+#include <sys/inotify.h>
+#include <sys/stat.h>
+#include <sys/sysconf.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/klog.h>
+#include <time.h>
+#include <unistd.h>
+#include <vector>
+#include <sys/prctl.h>
+
+#define LOG_TAG "dumpstate"
+#include <cutils/debugger.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include <selinux/android.h>
+
+#include "dumpstate.h"
+
+static const int64_t NANOS_PER_SEC = 1000000000;
+
+/* list of native processes to include in the native dumps */
+// This matches the /proc/pid/exe link instead of /proc/pid/cmdline.
+static const char* native_processes_to_dump[] = {
+        "/system/bin/audioserver",
+        "/system/bin/cameraserver",
+        "/system/bin/drmserver",
+        "/system/bin/mediacodec",     // media.codec
+        "/system/bin/mediadrmserver",
+        "/system/bin/mediaextractor", // media.extractor
+        "/system/bin/mediaserver",
+        "/system/bin/sdcard",
+        "/system/bin/surfaceflinger",
+        "/system/bin/vehicle_network_service",
+        NULL,
+};
+
+DurationReporter::DurationReporter(const char *title) : DurationReporter(title, stdout) {}
+
+DurationReporter::DurationReporter(const char *title, FILE *out) {
+    title_ = title;
+    if (title) {
+        started_ = DurationReporter::nanotime();
+    }
+    out_ = out;
+}
+
+DurationReporter::~DurationReporter() {
+    if (title_) {
+        uint64_t elapsed = DurationReporter::nanotime() - started_;
+        // Use "Yoda grammar" to make it easier to grep|sort sections.
+        if (out_) {
+            fprintf(out_, "------ %.3fs was the duration of '%s' ------\n",
+                   (float) elapsed / NANOS_PER_SEC, title_);
+        } else {
+            MYLOGD("Duration of '%s': %.3fs\n", title_, (float) elapsed / NANOS_PER_SEC);
+        }
+    }
+}
+
+uint64_t DurationReporter::DurationReporter::nanotime() {
+    struct timespec ts;
+    clock_gettime(CLOCK_MONOTONIC, &ts);
+    return (uint64_t) ts.tv_sec * NANOS_PER_SEC + ts.tv_nsec;
+}
+
+void for_each_userid(void (*func)(int), const char *header) {
+    ON_DRY_RUN_RETURN();
+    DIR *d;
+    struct dirent *de;
+
+    if (header) printf("\n------ %s ------\n", header);
+    func(0);
+
+    if (!(d = opendir("/data/system/users"))) {
+        printf("Failed to open /data/system/users (%s)\n", strerror(errno));
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        int userid;
+        if (de->d_type != DT_DIR || !(userid = atoi(de->d_name))) {
+            continue;
+        }
+        func(userid);
+    }
+
+    closedir(d);
+}
+
+static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
+    DIR *d;
+    struct dirent *de;
+
+    if (!(d = opendir("/proc"))) {
+        printf("Failed to open /proc (%s)\n", strerror(errno));
+        return;
+    }
+
+    if (header) printf("\n------ %s ------\n", header);
+    while ((de = readdir(d))) {
+        int pid;
+        int fd;
+        char cmdpath[255];
+        char cmdline[255];
+
+        if (!(pid = atoi(de->d_name))) {
+            continue;
+        }
+
+        memset(cmdline, 0, sizeof(cmdline));
+
+        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/cmdline", pid);
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+            TEMP_FAILURE_RETRY(read(fd, cmdline, sizeof(cmdline) - 2));
+            close(fd);
+            if (cmdline[0]) {
+                helper(pid, cmdline, arg);
+                continue;
+            }
+        }
+
+        // if no cmdline, a kernel thread has comm
+        snprintf(cmdpath, sizeof(cmdpath), "/proc/%d/comm", pid);
+        if ((fd = TEMP_FAILURE_RETRY(open(cmdpath, O_RDONLY | O_CLOEXEC))) >= 0) {
+            TEMP_FAILURE_RETRY(read(fd, cmdline + 1, sizeof(cmdline) - 4));
+            close(fd);
+            if (cmdline[1]) {
+                cmdline[0] = '[';
+                size_t len = strcspn(cmdline, "\f\b\r\n");
+                cmdline[len] = ']';
+                cmdline[len+1] = '\0';
+            }
+        }
+        if (!cmdline[0]) {
+            strcpy(cmdline, "N/A");
+        }
+        helper(pid, cmdline, arg);
+    }
+
+    closedir(d);
+}
+
+static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
+    for_each_pid_func *func = (for_each_pid_func*) arg;
+    func(pid, cmdline);
+}
+
+void for_each_pid(for_each_pid_func func, const char *header) {
+    ON_DRY_RUN_RETURN();
+  __for_each_pid(for_each_pid_helper, header, (void *)func);
+}
+
+static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
+    DIR *d;
+    struct dirent *de;
+    char taskpath[255];
+    for_each_tid_func *func = (for_each_tid_func *) arg;
+
+    sprintf(taskpath, "/proc/%d/task", pid);
+
+    if (!(d = opendir(taskpath))) {
+        printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
+        return;
+    }
+
+    func(pid, pid, cmdline);
+
+    while ((de = readdir(d))) {
+        int tid;
+        int fd;
+        char commpath[255];
+        char comm[255];
+
+        if (!(tid = atoi(de->d_name))) {
+            continue;
+        }
+
+        if (tid == pid)
+            continue;
+
+        sprintf(commpath,"/proc/%d/comm", tid);
+        memset(comm, 0, sizeof(comm));
+        if ((fd = TEMP_FAILURE_RETRY(open(commpath, O_RDONLY | O_CLOEXEC))) < 0) {
+            strcpy(comm, "N/A");
+        } else {
+            char *c;
+            TEMP_FAILURE_RETRY(read(fd, comm, sizeof(comm) - 2));
+            close(fd);
+
+            c = strrchr(comm, '\n');
+            if (c) {
+                *c = '\0';
+            }
+        }
+        func(pid, tid, comm);
+    }
+
+    closedir(d);
+}
+
+void for_each_tid(for_each_tid_func func, const char *header) {
+    ON_DRY_RUN_RETURN();
+    __for_each_pid(for_each_tid_helper, header, (void *) func);
+}
+
+void show_wchan(int pid, int tid, const char *name) {
+    ON_DRY_RUN_RETURN();
+    char path[255];
+    char buffer[255];
+    int fd, ret, save_errno;
+    char name_buffer[255];
+
+    memset(buffer, 0, sizeof(buffer));
+
+    sprintf(path, "/proc/%d/wchan", tid);
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    save_errno = errno;
+    close(fd);
+
+    if (ret < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+        return;
+    }
+
+    snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
+             pid == tid ? 0 : 3, "", name);
+
+    printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
+
+    return;
+}
+
+// print time in centiseconds
+static void snprcent(char *buffer, size_t len, size_t spc,
+                     unsigned long long time) {
+    static long hz; // cache discovered hz
+
+    if (hz <= 0) {
+        hz = sysconf(_SC_CLK_TCK);
+        if (hz <= 0) {
+            hz = 1000;
+        }
+    }
+
+    // convert to centiseconds
+    time = (time * 100 + (hz / 2)) / hz;
+
+    char str[16];
+
+    snprintf(str, sizeof(str), " %llu.%02u",
+             time / 100, (unsigned)(time % 100));
+    size_t offset = strlen(buffer);
+    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+// print permille as a percent
+static void snprdec(char *buffer, size_t len, size_t spc, unsigned permille) {
+    char str[16];
+
+    snprintf(str, sizeof(str), " %u.%u%%", permille / 10, permille % 10);
+    size_t offset = strlen(buffer);
+    snprintf(buffer + offset, (len > offset) ? len - offset : 0,
+             "%*s", (spc > offset) ? (int)(spc - offset) : 0, str);
+}
+
+void show_showtime(int pid, const char *name) {
+    ON_DRY_RUN_RETURN();
+    char path[255];
+    char buffer[1023];
+    int fd, ret, save_errno;
+
+    memset(buffer, 0, sizeof(buffer));
+
+    sprintf(path, "/proc/%d/stat", pid);
+    if ((fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC))) < 0) {
+        printf("Failed to open '%s' (%s)\n", path, strerror(errno));
+        return;
+    }
+
+    ret = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    save_errno = errno;
+    close(fd);
+
+    if (ret < 0) {
+        printf("Failed to read '%s' (%s)\n", path, strerror(save_errno));
+        return;
+    }
+
+    // field 14 is utime
+    // field 15 is stime
+    // field 42 is iotime
+    unsigned long long utime = 0, stime = 0, iotime = 0;
+    if (sscanf(buffer,
+               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %llu %llu %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %*d %*d %*d %*d %*d %*d %*d %llu ",
+               &utime, &stime, &iotime) != 3) {
+        return;
+    }
+
+    unsigned long long total = utime + stime;
+    if (!total) {
+        return;
+    }
+
+    unsigned permille = (iotime * 1000 + (total / 2)) / total;
+    if (permille > 1000) {
+        permille = 1000;
+    }
+
+    // try to beautify and stabilize columns at <80 characters
+    snprintf(buffer, sizeof(buffer), "%-6d%s", pid, name);
+    if ((name[0] != '[') || utime) {
+        snprcent(buffer, sizeof(buffer), 57, utime);
+    }
+    snprcent(buffer, sizeof(buffer), 65, stime);
+    if ((name[0] != '[') || iotime) {
+        snprcent(buffer, sizeof(buffer), 73, iotime);
+    }
+    if (iotime) {
+        snprdec(buffer, sizeof(buffer), 79, permille);
+    }
+    puts(buffer); // adds a trailing newline
+
+    return;
+}
+
+void do_dmesg() {
+    const char *title = "KERNEL LOG (dmesg)";
+    DurationReporter duration_reporter(title);
+    printf("------ %s ------\n", title);
+
+    ON_DRY_RUN_RETURN();
+    /* Get size of kernel buffer */
+    int size = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
+    if (size <= 0) {
+        printf("Unexpected klogctl return value: %d\n\n", size);
+        return;
+    }
+    char *buf = (char *) malloc(size + 1);
+    if (buf == NULL) {
+        printf("memory allocation failed\n\n");
+        return;
+    }
+    int retval = klogctl(KLOG_READ_ALL, buf, size);
+    if (retval < 0) {
+        printf("klogctl failure\n\n");
+        free(buf);
+        return;
+    }
+    buf[retval] = '\0';
+    printf("%s\n\n", buf);
+    free(buf);
+    return;
+}
+
+void do_showmap(int pid, const char *name) {
+    char title[255];
+    char arg[255];
+
+    sprintf(title, "SHOW MAP %d (%s)", pid, name);
+    sprintf(arg, "%d", pid);
+    run_command(title, 10, SU_PATH, "root", "showmap", "-q", arg, NULL);
+}
+
+static int _dump_file_from_fd(const char *title, const char *path, int fd) {
+    if (title) {
+        printf("------ %s (%s", title, path);
+
+        struct stat st;
+        // Only show the modification time of non-device files.
+        size_t path_len = strlen(path);
+        if ((path_len < 6 || memcmp(path, "/proc/", 6)) &&
+                (path_len < 5 || memcmp(path, "/sys/", 5)) &&
+                (path_len < 3 || memcmp(path, "/d/", 3)) &&
+                !fstat(fd, &st)) {
+            char stamp[80];
+            time_t mtime = st.st_mtime;
+            strftime(stamp, sizeof(stamp), "%Y-%m-%d %H:%M:%S", localtime(&mtime));
+            printf(": %s", stamp);
+        }
+        printf(") ------\n");
+    }
+    ON_DRY_RUN({ update_progress(WEIGHT_FILE); close(fd); return 0; });
+
+    bool newline = false;
+    fd_set read_set;
+    struct timeval tm;
+    while (1) {
+        FD_ZERO(&read_set);
+        FD_SET(fd, &read_set);
+        /* Timeout if no data is read for 30 seconds. */
+        tm.tv_sec = 30;
+        tm.tv_usec = 0;
+        uint64_t elapsed = DurationReporter::nanotime();
+        int ret = TEMP_FAILURE_RETRY(select(fd + 1, &read_set, NULL, NULL, &tm));
+        if (ret == -1) {
+            printf("*** %s: select failed: %s\n", path, strerror(errno));
+            newline = true;
+            break;
+        } else if (ret == 0) {
+            elapsed = DurationReporter::nanotime() - elapsed;
+            printf("*** %s: Timed out after %.3fs\n", path,
+                   (float) elapsed / NANOS_PER_SEC);
+            newline = true;
+            break;
+        } else {
+            char buffer[65536];
+            ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+            if (bytes_read > 0) {
+                fwrite(buffer, bytes_read, 1, stdout);
+                newline = (buffer[bytes_read-1] == '\n');
+            } else {
+                if (bytes_read == -1) {
+                    printf("*** %s: Failed to read from fd: %s", path, strerror(errno));
+                    newline = true;
+                }
+                break;
+            }
+        }
+    }
+    update_progress(WEIGHT_FILE);
+    close(fd);
+
+    if (!newline) printf("\n");
+    if (title) printf("\n");
+    return 0;
+}
+
+/* prints the contents of a file */
+int dump_file(const char *title, const char *path) {
+    DurationReporter duration_reporter(title);
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+    if (fd < 0) {
+        int err = errno;
+        printf("*** %s: %s\n", path, strerror(err));
+        if (title) printf("\n");
+        return -1;
+    }
+    return _dump_file_from_fd(title, path, fd);
+}
+
+int read_file_as_long(const char *path, long int *output) {
+    int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+    if (fd < 0) {
+        int err = errno;
+        MYLOGE("Error opening file descriptor for %s: %s\n", path, strerror(err));
+        return -1;
+    }
+    char buffer[50];
+    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    if (bytes_read == -1) {
+        MYLOGE("Error reading file %s: %s\n", path, strerror(errno));
+        return -2;
+    }
+    if (bytes_read == 0) {
+        MYLOGE("File %s is empty\n", path);
+        return -3;
+    }
+    *output = atoi(buffer);
+    return 0;
+}
+
+/* calls skip to gate calling dump_from_fd recursively
+ * in the specified directory. dump_from_fd defaults to
+ * dump_file_from_fd above when set to NULL. skip defaults
+ * to false when set to NULL. dump_from_fd will always be
+ * called with title NULL.
+ */
+int dump_files(const char *title, const char *dir,
+        bool (*skip)(const char *path),
+        int (*dump_from_fd)(const char *title, const char *path, int fd)) {
+    DurationReporter duration_reporter(title);
+    DIR *dirp;
+    struct dirent *d;
+    char *newpath = NULL;
+    const char *slash = "/";
+    int fd, retval = 0;
+
+    if (title) {
+        printf("------ %s (%s) ------\n", title, dir);
+    }
+    ON_DRY_RUN_RETURN(0);
+
+    if (dir[strlen(dir) - 1] == '/') {
+        ++slash;
+    }
+    dirp = opendir(dir);
+    if (dirp == NULL) {
+        retval = -errno;
+        MYLOGE("%s: %s\n", dir, strerror(errno));
+        return retval;
+    }
+
+    if (!dump_from_fd) {
+        dump_from_fd = dump_file_from_fd;
+    }
+    for (; ((d = readdir(dirp))); free(newpath), newpath = NULL) {
+        if ((d->d_name[0] == '.')
+         && (((d->d_name[1] == '.') && (d->d_name[2] == '\0'))
+          || (d->d_name[1] == '\0'))) {
+            continue;
+        }
+        asprintf(&newpath, "%s%s%s%s", dir, slash, d->d_name,
+                 (d->d_type == DT_DIR) ? "/" : "");
+        if (!newpath) {
+            retval = -errno;
+            continue;
+        }
+        if (skip && (*skip)(newpath)) {
+            continue;
+        }
+        if (d->d_type == DT_DIR) {
+            int ret = dump_files(NULL, newpath, skip, dump_from_fd);
+            if (ret < 0) {
+                retval = ret;
+            }
+            continue;
+        }
+        fd = TEMP_FAILURE_RETRY(open(newpath, O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+        if (fd < 0) {
+            retval = fd;
+            printf("*** %s: %s\n", newpath, strerror(errno));
+            continue;
+        }
+        (*dump_from_fd)(NULL, newpath, fd);
+    }
+    closedir(dirp);
+    if (title) {
+        printf("\n");
+    }
+    return retval;
+}
+
+/* fd must have been opened with the flag O_NONBLOCK. With this flag set,
+ * it's possible to avoid issues where opening the file itself can get
+ * stuck.
+ */
+int dump_file_from_fd(const char *title, const char *path, int fd) {
+    int flags = fcntl(fd, F_GETFL);
+    if (flags == -1) {
+        printf("*** %s: failed to get flags on fd %d: %s\n", path, fd, strerror(errno));
+        close(fd);
+        return -1;
+    } else if (!(flags & O_NONBLOCK)) {
+        printf("*** %s: fd must have O_NONBLOCK set.\n", path);
+        close(fd);
+        return -1;
+    }
+    return _dump_file_from_fd(title, path, fd);
+}
+
+bool waitpid_with_timeout(pid_t pid, int timeout_seconds, int* status) {
+    sigset_t child_mask, old_mask;
+    sigemptyset(&child_mask);
+    sigaddset(&child_mask, SIGCHLD);
+
+    if (sigprocmask(SIG_BLOCK, &child_mask, &old_mask) == -1) {
+        printf("*** sigprocmask failed: %s\n", strerror(errno));
+        return false;
+    }
+
+    struct timespec ts;
+    ts.tv_sec = timeout_seconds;
+    ts.tv_nsec = 0;
+    int ret = TEMP_FAILURE_RETRY(sigtimedwait(&child_mask, NULL, &ts));
+    int saved_errno = errno;
+    // Set the signals back the way they were.
+    if (sigprocmask(SIG_SETMASK, &old_mask, NULL) == -1) {
+        printf("*** sigprocmask failed: %s\n", strerror(errno));
+        if (ret == 0) {
+            return false;
+        }
+    }
+    if (ret == -1) {
+        errno = saved_errno;
+        if (errno == EAGAIN) {
+            errno = ETIMEDOUT;
+        } else {
+            printf("*** sigtimedwait failed: %s\n", strerror(errno));
+        }
+        return false;
+    }
+
+    pid_t child_pid = waitpid(pid, status, WNOHANG);
+    if (child_pid != pid) {
+        if (child_pid != -1) {
+            printf("*** Waiting for pid %d, got pid %d instead\n", pid, child_pid);
+        } else {
+            printf("*** waitpid failed: %s\n", strerror(errno));
+        }
+        return false;
+    }
+    return true;
+}
+
+// TODO: refactor all those commands that convert args
+void format_args(const char* command, const char *args[], std::string *string);
+
+int run_command(const char *title, int timeout_seconds, const char *command, ...) {
+    DurationReporter duration_reporter(title);
+    fflush(stdout);
+
+    const char *args[1024] = {command};
+    size_t arg;
+    va_list ap;
+    va_start(ap, command);
+    if (title) printf("------ %s (%s", title, command);
+    bool null_terminated = false;
+    for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
+        args[arg] = va_arg(ap, const char *);
+        if (args[arg] == nullptr) {
+            null_terminated = true;
+            break;
+        }
+        // TODO: null_terminated check is not really working; line below would crash dumpstate if
+        // nullptr is missing
+        if (title) printf(" %s", args[arg]);
+    }
+    if (title) printf(") ------\n");
+    fflush(stdout);
+    if (!null_terminated) {
+        // Fail now, otherwise execvp() call on run_command_always() might hang.
+        std::string cmd;
+        format_args(command, args, &cmd);
+        MYLOGE("skipping command %s because its args were not NULL-terminated", cmd.c_str());
+        return -1;
+    }
+
+    ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
+
+    int status = run_command_always(title, DONT_DROP_ROOT, NORMAL_STDOUT, timeout_seconds, args);
+    va_end(ap);
+    return status;
+}
+
+int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...) {
+    DurationReporter duration_reporter(title);
+    fflush(stdout);
+
+    const char *args[1024] = {command};
+    size_t arg;
+    va_list ap;
+    va_start(ap, command);
+    if (title) printf("------ %s (%s", title, command);
+    bool null_terminated = false;
+    for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
+        args[arg] = va_arg(ap, const char *);
+        if (args[arg] == nullptr) {
+            null_terminated = true;
+            break;
+        }
+        // TODO: null_terminated check is not really working; line below would crash dumpstate if
+        // nullptr is missing
+        if (title) printf(" %s", args[arg]);
+    }
+    if (title) printf(") ------\n");
+    fflush(stdout);
+    if (!null_terminated) {
+        // Fail now, otherwise execvp() call on run_command_always() might hang.
+        std::string cmd;
+        format_args(command, args, &cmd);
+        MYLOGE("skipping command %s because its args were not NULL-terminated", cmd.c_str());
+        return -1;
+    }
+
+    ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });
+
+    int status = run_command_always(title, DROP_ROOT, NORMAL_STDOUT, timeout_seconds, args);
+    va_end(ap);
+    return status;
+}
+
+/* forks a command and waits for it to finish */
+int run_command_always(const char *title, RootMode root_mode, StdoutMode stdout_mode,
+        int timeout_seconds, const char *args[]) {
+    bool silent = (stdout_mode == REDIRECT_TO_STDERR);
+    // TODO: need to check if args is null-terminated, otherwise execvp will crash dumpstate
+
+    /* TODO: for now we're simplifying the progress calculation by using the timeout as the weight.
+     * It's a good approximation for most cases, except when calling dumpsys, where its weight
+     * should be much higher proportionally to its timeout. */
+    int weight = timeout_seconds;
+
+    const char *command = args[0];
+    uint64_t start = DurationReporter::nanotime();
+    pid_t pid = fork();
+
+    /* handle error case */
+    if (pid < 0) {
+        if (!silent) printf("*** fork: %s\n", strerror(errno));
+        MYLOGE("*** fork: %s\n", strerror(errno));
+        return pid;
+    }
+
+    /* handle child case */
+    if (pid == 0) {
+        if (root_mode == DROP_ROOT && !drop_root_user()) {
+        if (!silent) printf("*** fail todrop root before running %s: %s\n", command,
+                strerror(errno));
+            MYLOGE("*** could not drop root before running %s: %s\n", command, strerror(errno));
+            return -1;
+        }
+
+        if (silent) {
+            // Redirect stderr to stdout
+            dup2(STDERR_FILENO, STDOUT_FILENO);
+        }
+
+        /* make sure the child dies when dumpstate dies */
+        prctl(PR_SET_PDEATHSIG, SIGKILL);
+
+        /* just ignore SIGPIPE, will go down with parent's */
+        struct sigaction sigact;
+        memset(&sigact, 0, sizeof(sigact));
+        sigact.sa_handler = SIG_IGN;
+        sigaction(SIGPIPE, &sigact, NULL);
+
+        execvp(command, (char**) args);
+        // execvp's result will be handled after waitpid_with_timeout() below, but if it failed,
+        // it's safer to exit dumpstate.
+        MYLOGD("execvp on command '%s' failed (error: %s)", command, strerror(errno));
+        fflush(stdout);
+        // Must call _exit (instead of exit), otherwise it will corrupt the zip file.
+        _exit(EXIT_FAILURE);
+    }
+
+    /* handle parent case */
+    int status;
+    bool ret = waitpid_with_timeout(pid, timeout_seconds, &status);
+    uint64_t elapsed = DurationReporter::nanotime() - start;
+    std::string cmd; // used to log command and its args
+    if (!ret) {
+        if (errno == ETIMEDOUT) {
+            format_args(command, args, &cmd);
+            if (!silent) printf("*** command '%s' timed out after %.3fs (killing pid %d)\n",
+            cmd.c_str(), (float) elapsed / NANOS_PER_SEC, pid);
+            MYLOGE("command '%s' timed out after %.3fs (killing pid %d)\n", cmd.c_str(),
+                   (float) elapsed / NANOS_PER_SEC, pid);
+        } else {
+            format_args(command, args, &cmd);
+            if (!silent) printf("*** command '%s': Error after %.4fs (killing pid %d)\n",
+            cmd.c_str(), (float) elapsed / NANOS_PER_SEC, pid);
+            MYLOGE("command '%s': Error after %.4fs (killing pid %d)\n", cmd.c_str(),
+                   (float) elapsed / NANOS_PER_SEC, pid);
+        }
+        kill(pid, SIGTERM);
+        if (!waitpid_with_timeout(pid, 5, NULL)) {
+            kill(pid, SIGKILL);
+            if (!waitpid_with_timeout(pid, 5, NULL)) {
+                if (!silent) printf("could not kill command '%s' (pid %d) even with SIGKILL.\n",
+                        command, pid);
+                MYLOGE("could not kill command '%s' (pid %d) even with SIGKILL.\n", command, pid);
+            }
+        }
+        return -1;
+    } else if (status) {
+        format_args(command, args, &cmd);
+        if (!silent) printf("*** command '%s' failed: %s\n", cmd.c_str(), strerror(errno));
+        MYLOGE("command '%s' failed: %s\n", cmd.c_str(), strerror(errno));
+        return -2;
+    }
+
+    if (WIFSIGNALED(status)) {
+        if (!silent) printf("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
+        MYLOGE("*** %s: Killed by signal %d\n", command, WTERMSIG(status));
+    } else if (WIFEXITED(status) && WEXITSTATUS(status) > 0) {
+        if (!silent) printf("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
+        MYLOGE("*** %s: Exit code %d\n", command, WEXITSTATUS(status));
+    }
+
+    if (weight > 0) {
+        update_progress(weight);
+    }
+    return status;
+}
+
+bool drop_root_user() {
+    if (getgid() == AID_SHELL && getuid() == AID_SHELL) {
+        MYLOGD("drop_root_user(): already running as Shell");
+        return true;
+    }
+    /* ensure we will keep capabilities when we drop root */
+    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+        MYLOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
+        return false;
+    }
+
+    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
+            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
+    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
+        MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
+        return false;
+    }
+    if (setgid(AID_SHELL) != 0) {
+        MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
+        return false;
+    }
+    if (setuid(AID_SHELL) != 0) {
+        MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
+        return false;
+    }
+
+    struct __user_cap_header_struct capheader;
+    struct __user_cap_data_struct capdata[2];
+    memset(&capheader, 0, sizeof(capheader));
+    memset(&capdata, 0, sizeof(capdata));
+    capheader.version = _LINUX_CAPABILITY_VERSION_3;
+    capheader.pid = 0;
+
+    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
+    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
+    capdata[0].inheritable = 0;
+    capdata[1].inheritable = 0;
+
+    if (capset(&capheader, &capdata[0]) < 0) {
+        MYLOGE("capset failed: %s\n", strerror(errno));
+        return false;
+    }
+
+    return true;
+}
+
+void send_broadcast(const std::string& action, const std::vector<std::string>& args) {
+    if (args.size() > 1000) {
+        MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
+        return;
+    }
+    const char *am_args[1024] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
+                                  action.c_str() };
+    size_t am_index = 5; // Starts at the index of last initial value above.
+    for (const std::string& arg : args) {
+        am_args[++am_index] = arg.c_str();
+    }
+    // Always terminate with NULL.
+    am_args[am_index + 1] = NULL;
+    std::string args_string;
+    format_args(am_index + 1, am_args, &args_string);
+    MYLOGD("send_broadcast command: %s\n", args_string.c_str());
+    run_command_always(NULL, DROP_ROOT, REDIRECT_TO_STDERR, 20, am_args);
+}
+
+size_t num_props = 0;
+static char* props[2000];
+
+static void print_prop(const char *key, const char *name, void *user) {
+    (void) user;
+    if (num_props < sizeof(props) / sizeof(props[0])) {
+        char buf[PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 10];
+        snprintf(buf, sizeof(buf), "[%s]: [%s]\n", key, name);
+        props[num_props++] = strdup(buf);
+    }
+}
+
+static int compare_prop(const void *a, const void *b) {
+    return strcmp(*(char * const *) a, *(char * const *) b);
+}
+
+/* prints all the system properties */
+void print_properties() {
+    const char* title = "SYSTEM PROPERTIES";
+    DurationReporter duration_reporter(title);
+    printf("------ %s ------\n", title);
+    ON_DRY_RUN_RETURN();
+    size_t i;
+    num_props = 0;
+    property_list(print_prop, NULL);
+    qsort(&props, num_props, sizeof(props[0]), compare_prop);
+
+    for (i = 0; i < num_props; ++i) {
+        fputs(props[i], stdout);
+        free(props[i]);
+    }
+    printf("\n");
+}
+
+int open_socket(const char *service) {
+    int s = android_get_control_socket(service);
+    if (s < 0) {
+        MYLOGE("android_get_control_socket(%s): %s\n", service, strerror(errno));
+        exit(1);
+    }
+    fcntl(s, F_SETFD, FD_CLOEXEC);
+    if (listen(s, 4) < 0) {
+        MYLOGE("listen(control socket): %s\n", strerror(errno));
+        exit(1);
+    }
+
+    struct sockaddr addr;
+    socklen_t alen = sizeof(addr);
+    int fd = accept(s, &addr, &alen);
+    if (fd < 0) {
+        MYLOGE("accept(control socket): %s\n", strerror(errno));
+        exit(1);
+    }
+
+    return fd;
+}
+
+/* redirect output to a service control socket */
+void redirect_to_socket(FILE *redirect, const char *service) {
+    int fd = open_socket(service);
+    fflush(redirect);
+    dup2(fd, fileno(redirect));
+    close(fd);
+}
+
+// TODO: should call is_valid_output_file and/or be merged into it.
+void create_parent_dirs(const char *path) {
+    char *chp = const_cast<char *> (path);
+
+    /* skip initial slash */
+    if (chp[0] == '/')
+        chp++;
+
+    /* create leading directories, if necessary */
+    struct stat dir_stat;
+    while (chp && chp[0]) {
+        chp = strchr(chp, '/');
+        if (chp) {
+            *chp = 0;
+            if (stat(path, &dir_stat) == -1 || !S_ISDIR(dir_stat.st_mode)) {
+                MYLOGI("Creating directory %s\n", path);
+                if (mkdir(path, 0770)) { /* drwxrwx--- */
+                    MYLOGE("Unable to create directory %s: %s\n", path, strerror(errno));
+                } else if (chown(path, AID_SHELL, AID_SHELL)) {
+                    MYLOGE("Unable to change ownership of dir %s: %s\n", path, strerror(errno));
+                }
+            }
+            *chp++ = '/';
+        }
+    }
+}
+
+/* redirect output to a file */
+void redirect_to_file(FILE *redirect, char *path) {
+    create_parent_dirs(path);
+
+    int fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
+                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+    if (fd < 0) {
+        MYLOGE("%s: %s\n", path, strerror(errno));
+        exit(1);
+    }
+
+    TEMP_FAILURE_RETRY(dup2(fd, fileno(redirect)));
+    close(fd);
+}
+
+static bool should_dump_native_traces(const char* path) {
+    for (const char** p = native_processes_to_dump; *p; p++) {
+        if (!strcmp(*p, path)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/* dump Dalvik and native stack traces, return the trace file location (NULL if none) */
+const char *dump_traces() {
+    DurationReporter duration_reporter("DUMP TRACES", NULL);
+    ON_DRY_RUN_RETURN(NULL);
+    const char* result = NULL;
+
+    char traces_path[PROPERTY_VALUE_MAX] = "";
+    property_get("dalvik.vm.stack-trace-file", traces_path, "");
+    if (!traces_path[0]) return NULL;
+
+    /* move the old traces.txt (if any) out of the way temporarily */
+    char anr_traces_path[PATH_MAX];
+    strlcpy(anr_traces_path, traces_path, sizeof(anr_traces_path));
+    strlcat(anr_traces_path, ".anr", sizeof(anr_traces_path));
+    if (rename(traces_path, anr_traces_path) && errno != ENOENT) {
+        MYLOGE("rename(%s, %s): %s\n", traces_path, anr_traces_path, strerror(errno));
+        return NULL;  // Can't rename old traces.txt -- no permission? -- leave it alone instead
+    }
+
+    /* create a new, empty traces.txt file to receive stack dumps */
+    int fd = TEMP_FAILURE_RETRY(open(traces_path, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW | O_CLOEXEC,
+                                     0666));  /* -rw-rw-rw- */
+    if (fd < 0) {
+        MYLOGE("%s: %s\n", traces_path, strerror(errno));
+        return NULL;
+    }
+    int chmod_ret = fchmod(fd, 0666);
+    if (chmod_ret < 0) {
+        MYLOGE("fchmod on %s failed: %s\n", traces_path, strerror(errno));
+        close(fd);
+        return NULL;
+    }
+
+    /* Variables below must be initialized before 'goto' statements */
+    int dalvik_found = 0;
+    int ifd, wfd = -1;
+
+    /* walk /proc and kill -QUIT all Dalvik processes */
+    DIR *proc = opendir("/proc");
+    if (proc == NULL) {
+        MYLOGE("/proc: %s\n", strerror(errno));
+        goto error_close_fd;
+    }
+
+    /* use inotify to find when processes are done dumping */
+    ifd = inotify_init();
+    if (ifd < 0) {
+        MYLOGE("inotify_init: %s\n", strerror(errno));
+        goto error_close_fd;
+    }
+
+    wfd = inotify_add_watch(ifd, traces_path, IN_CLOSE_WRITE);
+    if (wfd < 0) {
+        MYLOGE("inotify_add_watch(%s): %s\n", traces_path, strerror(errno));
+        goto error_close_ifd;
+    }
+
+    struct dirent *d;
+    while ((d = readdir(proc))) {
+        int pid = atoi(d->d_name);
+        if (pid <= 0) continue;
+
+        char path[PATH_MAX];
+        char data[PATH_MAX];
+        snprintf(path, sizeof(path), "/proc/%d/exe", pid);
+        ssize_t len = readlink(path, data, sizeof(data) - 1);
+        if (len <= 0) {
+            continue;
+        }
+        data[len] = '\0';
+
+        if (!strncmp(data, "/system/bin/app_process", strlen("/system/bin/app_process"))) {
+            /* skip zygote -- it won't dump its stack anyway */
+            snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+            int cfd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
+            len = read(cfd, data, sizeof(data) - 1);
+            close(cfd);
+            if (len <= 0) {
+                continue;
+            }
+            data[len] = '\0';
+            if (!strncmp(data, "zygote", strlen("zygote"))) {
+                continue;
+            }
+
+            ++dalvik_found;
+            uint64_t start = DurationReporter::nanotime();
+            if (kill(pid, SIGQUIT)) {
+                MYLOGE("kill(%d, SIGQUIT): %s\n", pid, strerror(errno));
+                continue;
+            }
+
+            /* wait for the writable-close notification from inotify */
+            struct pollfd pfd = { ifd, POLLIN, 0 };
+            int ret = poll(&pfd, 1, 5000);  /* 5 sec timeout */
+            if (ret < 0) {
+                MYLOGE("poll: %s\n", strerror(errno));
+            } else if (ret == 0) {
+                MYLOGE("warning: timed out dumping pid %d\n", pid);
+            } else {
+                struct inotify_event ie;
+                read(ifd, &ie, sizeof(ie));
+            }
+
+            if (lseek(fd, 0, SEEK_END) < 0) {
+                MYLOGE("lseek: %s\n", strerror(errno));
+            } else {
+                dprintf(fd, "[dump dalvik stack %d: %.3fs elapsed]\n",
+                        pid, (float)(DurationReporter::nanotime() - start) / NANOS_PER_SEC);
+            }
+        } else if (should_dump_native_traces(data)) {
+            /* dump native process if appropriate */
+            if (lseek(fd, 0, SEEK_END) < 0) {
+                MYLOGE("lseek: %s\n", strerror(errno));
+            } else {
+                static uint16_t timeout_failures = 0;
+                uint64_t start = DurationReporter::nanotime();
+
+                /* If 3 backtrace dumps fail in a row, consider debuggerd dead. */
+                if (timeout_failures == 3) {
+                    dprintf(fd, "too many stack dump failures, skipping...\n");
+                } else if (dump_backtrace_to_file_timeout(pid, fd, 20) == -1) {
+                    dprintf(fd, "dumping failed, likely due to a timeout\n");
+                    timeout_failures++;
+                } else {
+                    timeout_failures = 0;
+                }
+                dprintf(fd, "[dump native stack %d: %.3fs elapsed]\n",
+                        pid, (float)(DurationReporter::nanotime() - start) / NANOS_PER_SEC);
+            }
+        }
+    }
+
+    if (dalvik_found == 0) {
+        MYLOGE("Warning: no Dalvik processes found to dump stacks\n");
+    }
+
+    static char dump_traces_path[PATH_MAX];
+    strlcpy(dump_traces_path, traces_path, sizeof(dump_traces_path));
+    strlcat(dump_traces_path, ".bugreport", sizeof(dump_traces_path));
+    if (rename(traces_path, dump_traces_path)) {
+        MYLOGE("rename(%s, %s): %s\n", traces_path, dump_traces_path, strerror(errno));
+        goto error_close_ifd;
+    }
+    result = dump_traces_path;
+
+    /* replace the saved [ANR] traces.txt file */
+    rename(anr_traces_path, traces_path);
+
+error_close_ifd:
+    close(ifd);
+error_close_fd:
+    close(fd);
+    return result;
+}
+
+void dump_route_tables() {
+    DurationReporter duration_reporter("DUMP ROUTE TABLES");
+    ON_DRY_RUN_RETURN();
+    const char* const RT_TABLES_PATH = "/data/misc/net/rt_tables";
+    dump_file("RT_TABLES", RT_TABLES_PATH);
+    FILE* fp = fopen(RT_TABLES_PATH, "re");
+    if (!fp) {
+        printf("*** %s: %s\n", RT_TABLES_PATH, strerror(errno));
+        return;
+    }
+    char table[16];
+    // Each line has an integer (the table number), a space, and a string (the table name). We only
+    // need the table number. It's a 32-bit unsigned number, so max 10 chars. Skip the table name.
+    // Add a fixed max limit so this doesn't go awry.
+    for (int i = 0; i < 64 && fscanf(fp, " %10s %*s", table) == 1; ++i) {
+        run_command("ROUTE TABLE IPv4", 10, "ip", "-4", "route", "show", "table", table, NULL);
+        run_command("ROUTE TABLE IPv6", 10, "ip", "-6", "route", "show", "table", table, NULL);
+    }
+    fclose(fp);
+}
+
+/* overall progress */
+int progress = 0;
+int do_update_progress = 0; // Set by dumpstate.cpp
+int weight_total = WEIGHT_TOTAL;
+
+// TODO: make this function thread safe if sections are generated in parallel.
+void update_progress(int delta) {
+    if (!do_update_progress) return;
+
+    progress += delta;
+
+    char key[PROPERTY_KEY_MAX];
+    char value[PROPERTY_VALUE_MAX];
+
+    // adjusts max on the fly
+    if (progress > weight_total) {
+        int new_total = weight_total * 1.2;
+        MYLOGD("Adjusting total weight from %d to %d\n", weight_total, new_total);
+        weight_total = new_total;
+        sprintf(key, "dumpstate.%d.max", getpid());
+        sprintf(value, "%d", weight_total);
+        int status = property_set(key, value);
+        if (status) {
+            MYLOGE("Could not update max weight by setting system property %s to %s: %d\n",
+                    key, value, status);
+        }
+    }
+
+    sprintf(key, "dumpstate.%d.progress", getpid());
+    sprintf(value, "%d", progress);
+
+    if (progress % 100 == 0) {
+        // We don't want to spam logcat, so only log multiples of 100.
+        MYLOGD("Setting progress (%s): %s/%d\n", key, value, weight_total);
+    } else {
+        // stderr is ignored on normal invocations, but useful when calling /system/bin/dumpstate
+        // directly for debuggging.
+        fprintf(stderr, "Setting progress (%s): %s/%d\n", key, value, weight_total);
+    }
+
+    int status = property_set(key, value);
+    if (status) {
+        MYLOGE("Could not update progress by setting system property %s to %s: %d\n",
+                key, value, status);
+    }
+}
+
+void take_screenshot(const std::string& path) {
+    const char *args[] = { "/system/bin/screencap", "-p", path.c_str(), NULL };
+    run_command_always(NULL, DONT_DROP_ROOT, REDIRECT_TO_STDERR, 10, args);
+}
+
+void vibrate(FILE* vibrator, int ms) {
+    fprintf(vibrator, "%d\n", ms);
+    fflush(vibrator);
+}
+
+bool is_dir(const char* pathname) {
+    struct stat info;
+    if (stat(pathname, &info) == -1) {
+        return false;
+    }
+    return S_ISDIR(info.st_mode);
+}
+
+time_t get_mtime(int fd, time_t default_mtime) {
+    struct stat info;
+    if (fstat(fd, &info) == -1) {
+        return default_mtime;
+    }
+    return info.st_mtime;
+}
+
+void dump_emmc_ecsd(const char *ext_csd_path) {
+    static const size_t EXT_CSD_REV = 192;
+    static const size_t EXT_PRE_EOL_INFO = 267;
+    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268;
+    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269;
+    struct hex {
+        char str[2];
+    } buffer[512];
+    int fd, ext_csd_rev, ext_pre_eol_info;
+    ssize_t bytes_read;
+    static const char *ver_str[] = {
+        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
+    };
+    static const char *eol_str[] = {
+        "Undefined",
+        "Normal",
+        "Warning (consumed 80% of reserve)",
+        "Urgent (consumed 90% of reserve)"
+    };
+
+    printf("------ %s Extended CSD ------\n", ext_csd_path);
+
+    fd = TEMP_FAILURE_RETRY(open(ext_csd_path,
+                                 O_RDONLY | O_NONBLOCK | O_CLOEXEC));
+    if (fd < 0) {
+        printf("*** %s: %s\n\n", ext_csd_path, strerror(errno));
+        return;
+    }
+
+    bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, sizeof(buffer)));
+    close(fd);
+    if (bytes_read < 0) {
+        printf("*** %s: %s\n\n", ext_csd_path, strerror(errno));
+        return;
+    }
+    if (bytes_read < (ssize_t)(EXT_CSD_REV * sizeof(struct hex))) {
+        printf("*** %s: truncated content %zd\n\n", ext_csd_path, bytes_read);
+        return;
+    }
+
+    ext_csd_rev = 0;
+    if (sscanf(buffer[EXT_CSD_REV].str, "%02x", &ext_csd_rev) != 1) {
+        printf("*** %s: EXT_CSD_REV parse error \"%.2s\"\n\n",
+               ext_csd_path, buffer[EXT_CSD_REV].str);
+        return;
+    }
+
+    printf("rev 1.%d (MMC %s)\n",
+           ext_csd_rev,
+           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ?
+               ver_str[ext_csd_rev] :
+               "Unknown");
+    if (ext_csd_rev < 7) {
+        printf("\n");
+        return;
+    }
+
+    if (bytes_read < (ssize_t)(EXT_PRE_EOL_INFO * sizeof(struct hex))) {
+        printf("*** %s: truncated content %zd\n\n", ext_csd_path, bytes_read);
+        return;
+    }
+
+    ext_pre_eol_info = 0;
+    if (sscanf(buffer[EXT_PRE_EOL_INFO].str, "%02x", &ext_pre_eol_info) != 1) {
+        printf("*** %s: PRE_EOL_INFO parse error \"%.2s\"\n\n",
+               ext_csd_path, buffer[EXT_PRE_EOL_INFO].str);
+        return;
+    }
+    printf("PRE_EOL_INFO %d (MMC %s)\n",
+           ext_pre_eol_info,
+           eol_str[(ext_pre_eol_info < (int)
+                       (sizeof(eol_str) / sizeof(eol_str[0]))) ?
+                           ext_pre_eol_info : 0]);
+
+    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
+            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
+            ++lifetime) {
+        int ext_device_life_time_est;
+        static const char *est_str[] = {
+            "Undefined",
+            "0-10% of device lifetime used",
+            "10-20% of device lifetime used",
+            "20-30% of device lifetime used",
+            "30-40% of device lifetime used",
+            "40-50% of device lifetime used",
+            "50-60% of device lifetime used",
+            "60-70% of device lifetime used",
+            "70-80% of device lifetime used",
+            "80-90% of device lifetime used",
+            "90-100% of device lifetime used",
+            "Exceeded the maximum estimated device lifetime",
+        };
+
+        if (bytes_read < (ssize_t)(lifetime * sizeof(struct hex))) {
+            printf("*** %s: truncated content %zd\n", ext_csd_path, bytes_read);
+            break;
+        }
+
+        ext_device_life_time_est = 0;
+        if (sscanf(buffer[lifetime].str, "%02x", &ext_device_life_time_est) != 1) {
+            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%.2s\"\n",
+                   ext_csd_path,
+                   (unsigned)(lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) + 'A',
+                   buffer[lifetime].str);
+            continue;
+        }
+        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
+               (unsigned)(lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) + 'A',
+               ext_device_life_time_est,
+               est_str[(ext_device_life_time_est < (int)
+                           (sizeof(est_str) / sizeof(est_str[0]))) ?
+                               ext_device_life_time_est : 0]);
+    }
+
+    printf("\n");
+}
+
+// TODO: refactor all those commands that convert args
+void format_args(int argc, const char *argv[], std::string *args) {
+    LOG_ALWAYS_FATAL_IF(args == nullptr);
+    for (int i = 0; i < argc; i++) {
+        args->append(argv[i]);
+        if (i < argc -1) {
+          args->append(" ");
+        }
+    }
+}
+void format_args(const char* command, const char *args[], std::string *string) {
+    LOG_ALWAYS_FATAL_IF(args == nullptr || command == nullptr);
+    string->append(command);
+    if (args[0] == nullptr) return;
+    string->append(" ");
+
+    for (int arg = 1; arg <= 1000; ++arg) {
+        if (args[arg] == nullptr) return;
+        string->append(args[arg]);
+        if (args[arg+1] != nullptr) {
+            string->append(" ");
+        }
+    }
+    // TODO: not really working: if NULL is missing, it will crash dumpstate.
+    MYLOGE("internal error: missing NULL entry on %s", string->c_str());
+}
diff --git a/cmds/dumpsys/Android.mk b/cmds/dumpsys/Android.mk
index 9be0901..8335c14 100644
--- a/cmds/dumpsys/Android.mk
+++ b/cmds/dumpsys/Android.mk
@@ -5,10 +5,11 @@
 	dumpsys.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+	libbase \
 	libutils \
 	liblog \
 	libbinder
-	
+
 
 ifeq ($(TARGET_OS),linux)
 	LOCAL_CFLAGS += -DXP_UNIX
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index ce8993d..7e5bbc5 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -5,53 +5,149 @@
 
 #define LOG_TAG "dumpsys"
 
-#include <utils/Log.h>
+#include <algorithm>
+#include <chrono>
+#include <thread>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <binder/IServiceManager.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
 #include <binder/TextOutput.h>
+#include <utils/Log.h>
 #include <utils/Vector.h>
 
+#include <fcntl.h>
 #include <getopt.h>
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 using namespace android;
+using android::base::unique_fd;
+using android::base::WriteFully;
 
 static int sort_func(const String16* lhs, const String16* rhs)
 {
     return lhs->compare(*rhs);
 }
 
+static void usage() {
+    fprintf(stderr,
+        "usage: dumpsys\n"
+            "         To dump all services.\n"
+            "or:\n"
+            "       dumpsys [-t TIMEOUT] [--help | -l | --skip SERVICES | SERVICE [ARGS]]\n"
+            "         --help: shows this help\n"
+            "         -l: only list services, do not dump them\n"
+            "         -t TIMEOUT: TIMEOUT to use in seconds instead of default 10 seconds\n"
+            "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
+            "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
+}
+
+bool IsSkipped(const Vector<String16>& skipped, const String16& service) {
+    for (const auto& candidate : skipped) {
+        if (candidate == service) {
+            return true;
+        }
+    }
+    return false;
+}
+
 int main(int argc, char* const argv[])
 {
     signal(SIGPIPE, SIG_IGN);
     sp<IServiceManager> sm = defaultServiceManager();
     fflush(stdout);
     if (sm == NULL) {
-		ALOGE("Unable to get default service manager!");
+        ALOGE("Unable to get default service manager!");
         aerr << "dumpsys: Unable to get default service manager!" << endl;
         return 20;
     }
 
     Vector<String16> services;
     Vector<String16> args;
+    Vector<String16> skippedServices;
     bool showListOnly = false;
-    if ((argc == 2) && (strcmp(argv[1], "-l") == 0)) {
-        showListOnly = true;
+    bool skipServices = false;
+    int timeoutArg = 10;
+    static struct option longOptions[] = {
+        {"skip", no_argument, 0,  0 },
+        {"help", no_argument, 0,  0 },
+        {     0,           0, 0,  0 }
+    };
+
+    while (1) {
+        int c;
+        int optionIndex = 0;
+
+        c = getopt_long(argc, argv, "+t:l", longOptions, &optionIndex);
+
+        if (c == -1) {
+            break;
+        }
+
+        switch (c) {
+        case 0:
+            if (!strcmp(longOptions[optionIndex].name, "skip")) {
+                skipServices = true;
+            } else if (!strcmp(longOptions[optionIndex].name, "help")) {
+                usage();
+                return 0;
+            }
+            break;
+
+        case 't':
+            {
+                char *endptr;
+                timeoutArg = strtol(optarg, &endptr, 10);
+                if (*endptr != '\0' || timeoutArg <= 0) {
+                    fprintf(stderr, "Error: invalid timeout number: '%s'\n", optarg);
+                    return -1;
+                }
+            }
+            break;
+
+        case 'l':
+            showListOnly = true;
+            break;
+
+        default:
+            fprintf(stderr, "\n");
+            usage();
+            return -1;
+        }
     }
-    if ((argc == 1) || showListOnly) {
+
+    for (int i = optind; i < argc; i++) {
+        if (skipServices) {
+            skippedServices.add(String16(argv[i]));
+        } else {
+            if (i == optind) {
+                services.add(String16(argv[i]));
+            } else {
+                args.add(String16(argv[i]));
+            }
+        }
+    }
+
+    if ((skipServices && skippedServices.empty()) ||
+            (showListOnly && (!services.empty() || !skippedServices.empty()))) {
+        usage();
+        return -1;
+    }
+
+    if (services.empty() || showListOnly) {
+        // gets all services
         services = sm->listServices();
         services.sort(sort_func);
         args.add(String16("-a"));
-    } else {
-        services.add(String16(argv[1]));
-        for (int i=2; i<argc; i++) {
-            args.add(String16(argv[i]));
-        }
     }
 
     const size_t N = services.size();
@@ -59,11 +155,12 @@
     if (N > 1) {
         // first print a list of the current services
         aout << "Currently running services:" << endl;
-    
+
         for (size_t i=0; i<N; i++) {
             sp<IBinder> service = sm->checkService(services[i]);
             if (service != NULL) {
-                aout << "  " << services[i] << endl;
+                bool skipped = IsSkipped(skippedServices, services[i]);
+                aout << "  " << services[i] << (skipped ? " (skipped)" : "") << endl;
             }
         }
     }
@@ -72,21 +169,106 @@
         return 0;
     }
 
-    for (size_t i=0; i<N; i++) {
-        sp<IBinder> service = sm->checkService(services[i]);
+    for (size_t i = 0; i < N; i++) {
+        String16 service_name = std::move(services[i]);
+        if (IsSkipped(skippedServices, service_name)) continue;
+
+        sp<IBinder> service = sm->checkService(service_name);
         if (service != NULL) {
+            int sfd[2];
+
+            if (pipe(sfd) != 0) {
+                aerr << "Failed to create pipe to dump service info for " << service_name
+                     << ": " << strerror(errno) << endl;
+                continue;
+            }
+
+            unique_fd local_end(sfd[0]);
+            unique_fd remote_end(sfd[1]);
+            sfd[0] = sfd[1] = -1;
+
             if (N > 1) {
                 aout << "------------------------------------------------------------"
                         "-------------------" << endl;
-                aout << "DUMP OF SERVICE " << services[i] << ":" << endl;
+                aout << "DUMP OF SERVICE " << service_name << ":" << endl;
             }
-            int err = service->dump(STDOUT_FILENO, args);
-            if (err != 0) {
-                aerr << "Error dumping service info: (" << strerror(err)
-                        << ") " << services[i] << endl;
+
+            // dump blocks until completion, so spawn a thread..
+            std::thread dump_thread([=, remote_end { std::move(remote_end) }]() mutable {
+                int err = service->dump(remote_end.get(), args);
+
+                // It'd be nice to be able to close the remote end of the socketpair before the dump
+                // call returns, to terminate our reads if the other end closes their copy of the
+                // file descriptor, but then hangs for some reason. There doesn't seem to be a good
+                // way to do this, though.
+                remote_end.clear();
+
+                if (err != 0) {
+                    aerr << "Error dumping service info: (" << strerror(err) << ") " << service_name
+                         << endl;
+                }
+            });
+
+            auto timeout = std::chrono::seconds(timeoutArg);
+            auto end = std::chrono::steady_clock::now() + timeout;
+
+            struct pollfd pfd = {
+                .fd = local_end.get(),
+                .events = POLLIN
+            };
+
+            bool timed_out = false;
+            bool error = false;
+            while (true) {
+                // Wrap this in a lambda so that TEMP_FAILURE_RETRY recalculates the timeout.
+                auto time_left_ms = [end]() {
+                    auto now = std::chrono::steady_clock::now();
+                    auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(end - now);
+                    return std::max(diff.count(), 0ll);
+                };
+
+                int rc = TEMP_FAILURE_RETRY(poll(&pfd, 1, time_left_ms()));
+                if (rc < 0) {
+                    aerr << "Error in poll while dumping service " << service_name << " : "
+                         << strerror(errno) << endl;
+                    error = true;
+                    break;
+                } else if (rc == 0) {
+                    timed_out = true;
+                    break;
+                }
+
+                char buf[4096];
+                rc = TEMP_FAILURE_RETRY(read(local_end.get(), buf, sizeof(buf)));
+                if (rc < 0) {
+                    aerr << "Failed to read while dumping service " << service_name << ": "
+                         << strerror(errno) << endl;
+                    error = true;
+                    break;
+                } else if (rc == 0) {
+                    // EOF.
+                    break;
+                }
+
+                if (!WriteFully(STDOUT_FILENO, buf, rc)) {
+                    aerr << "Failed to write while dumping service " << service_name << ": "
+                         << strerror(errno) << endl;
+                    error = true;
+                    break;
+                }
+            }
+
+            if (timed_out) {
+                aout << endl << "*** SERVICE DUMP TIMEOUT EXPIRED ***" << endl << endl;
+            }
+
+            if (timed_out || error) {
+                dump_thread.detach();
+            } else {
+                dump_thread.join();
             }
         } else {
-            aerr << "Can't find service: " << services[i] << endl;
+            aerr << "Can't find service: " << service_name << endl;
         }
     }
 
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 3155766..ddf3aa8 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -207,7 +207,7 @@
     sp<GLConsumer> glc = new GLConsumer(consumer, name,
             GL_TEXTURE_EXTERNAL_OES, false, true);
     glc->setDefaultBufferSize(w, h);
-    glc->setDefaultMaxBufferCount(3);
+    producer->setMaxDequeuedBufferCount(2);
     glc->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
 
     sp<ANativeWindow> anw = new Surface(producer);
diff --git a/cmds/flatland/Main.cpp b/cmds/flatland/Main.cpp
index 866203f..c47b0c8 100644
--- a/cmds/flatland/Main.cpp
+++ b/cmds/flatland/Main.cpp
@@ -206,8 +206,8 @@
 
 static const ShaderDesc shaders[] = {
     {
-        name: "Blit",
-        vertexShader: {
+        .name="Blit",
+        .vertexShader={
             "precision mediump float;",
             "",
             "attribute vec4 position;",
@@ -223,7 +223,7 @@
             "    texCoords = uvToTex * uv;",
             "}",
         },
-        fragmentShader: {
+        .fragmentShader={
             "#extension GL_OES_EGL_image_external : require",
             "precision mediump float;",
             "",
@@ -240,8 +240,8 @@
     },
 
     {
-        name: "Gradient",
-        vertexShader: {
+        .name="Gradient",
+        .vertexShader={
             "precision mediump float;",
             "",
             "attribute vec4 position;",
@@ -257,7 +257,7 @@
             "    interp = (uvToInterp * uv).x;",
             "}",
         },
-        fragmentShader: {
+        .fragmentShader={
             "precision mediump float;",
             "",
             "varying float interp;",
diff --git a/cmds/installd/Android.mk b/cmds/installd/Android.mk
index 6dec7f6..d35099a 100644
--- a/cmds/installd/Android.mk
+++ b/cmds/installd/Android.mk
@@ -1,6 +1,6 @@
 LOCAL_PATH := $(call my-dir)
 
-common_src_files := commands.cpp utils.cpp
+common_src_files := commands.cpp globals.cpp utils.cpp
 common_cflags := -Wall -Werror
 
 #
@@ -15,6 +15,7 @@
 LOCAL_SHARED_LIBRARIES := \
     libbase \
     liblogwrap \
+    libselinux \
 
 LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
 LOCAL_CLANG := true
@@ -38,5 +39,77 @@
 
 LOCAL_STATIC_LIBRARIES := libdiskusage
 LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_INIT_RC := installd.rc
 LOCAL_CLANG := true
 include $(BUILD_EXECUTABLE)
+
+#
+# OTA Executable
+#
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := otapreopt
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := $(common_cflags)
+
+# Base & ASLR boundaries for boot image creation.
+ifndef LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA
+  LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA := -0x1000000
+else
+  LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA := $(LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
+endif
+ifndef LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA
+  LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA := 0x1000000
+else
+  LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA := $(LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
+endif
+LOCAL_CFLAGS += -DART_BASE_ADDRESS=$(LIBART_IMG_HOST_BASE_ADDRESS)
+LOCAL_CFLAGS += -DART_BASE_ADDRESS_MIN_DELTA=$(LOCAL_LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA)
+LOCAL_CFLAGS += -DART_BASE_ADDRESS_MAX_DELTA=$(LOCAL_LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA)
+
+LOCAL_SRC_FILES := otapreopt.cpp $(common_src_files)
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libcutils \
+    liblog \
+    liblogwrap \
+    libselinux \
+
+LOCAL_STATIC_LIBRARIES := libdiskusage
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_CLANG := true
+include $(BUILD_EXECUTABLE)
+
+# OTA chroot tool
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := otapreopt_chroot
+LOCAL_MODULE_TAGS := optional
+LOCAL_CFLAGS := $(common_cflags)
+
+LOCAL_SRC_FILES := otapreopt_chroot.cpp
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    liblog \
+
+LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_CLANG := true
+include $(BUILD_EXECUTABLE)
+
+# OTA postinstall script
+
+include $(CLEAR_VARS)
+LOCAL_MODULE:= otapreopt_script
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_SRC_FILES := otapreopt_script.sh
+
+# Let this depend on otapreopt and the chroot tool, so we just have to mention one in a
+# configuration.
+LOCAL_REQUIRED_MODULES := otapreopt otapreopt_chroot
+
+include $(BUILD_PREBUILT)
+
+# Tests.
+
+include $(LOCAL_PATH)/tests/Android.mk
\ No newline at end of file
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index c05a3d3..90ef277 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -14,172 +14,303 @@
 ** limitations under the License.
 */
 
-#include "installd.h"
+#include "commands.h"
 
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sys/capability.h>
+#include <sys/file.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/xattr.h>
+#include <unistd.h>
+
+#include <android-base/stringprintf.h>
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>               // TODO: Move everything to base/logging.
 #include <cutils/sched_policy.h>
 #include <diskusage/dirsize.h>
 #include <logwrap/logwrap.h>
-#include <system/thread_defs.h>
+#include <private/android_filesystem_config.h>
 #include <selinux/android.h>
+#include <system/thread_defs.h>
 
-#include <inttypes.h>
-#include <sys/capability.h>
-#include <sys/file.h>
-#include <unistd.h>
+#include <globals.h>
+#include <installd_deps.h>
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
 
 using android::base::StringPrintf;
 
-/* Directory records that are used in execution of commands. */
-dir_rec_t android_data_dir;
-dir_rec_t android_asec_dir;
-dir_rec_t android_app_dir;
-dir_rec_t android_app_private_dir;
-dir_rec_t android_app_lib_dir;
-dir_rec_t android_media_dir;
-dir_rec_t android_mnt_expand_dir;
-dir_rec_array_t android_system_dirs;
+namespace android {
+namespace installd {
 
-static const char* kCpPath = "/system/bin/cp";
+static constexpr const char* kCpPath = "/system/bin/cp";
+static constexpr const char* kXattrDefault = "user.default";
 
-int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
-{
-    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
-        ALOGE("invalid uid/gid: %d %d\n", uid, gid);
-        return -1;
+#define MIN_RESTRICTED_HOME_SDK_VERSION 24 // > M
+
+typedef int fd_t;
+
+static bool property_get_bool(const char* property_name, bool default_value = false) {
+    char tmp_property_value[kPropertyValueMax];
+    bool have_property = get_property(property_name, tmp_property_value, nullptr) > 0;
+    if (!have_property) {
+        return default_value;
+    }
+    return strcmp(tmp_property_value, "true") == 0;
+}
+
+int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+        appid_t appid, const char* seinfo, int target_sdk_version) {
+    uid_t uid = multiuser_get_uid(userid, appid);
+    int target_mode = target_sdk_version >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
+    if (flags & FLAG_STORAGE_CE) {
+        auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
+        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) != 0) {
+            PLOG(ERROR) << "Failed to prepare " << path;
+            return -1;
+        }
+        if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
+            PLOG(ERROR) << "Failed to setfilecon " << path;
+            return -1;
+        }
+    }
+    if (flags & FLAG_STORAGE_DE) {
+        auto path = create_data_user_de_package_path(uuid, userid, pkgname);
+        if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, uid) == -1) {
+            PLOG(ERROR) << "Failed to prepare " << path;
+            // TODO: include result once 25796509 is fixed
+            return 0;
+        }
+        if (selinux_android_setfilecon(path.c_str(), pkgname, seinfo, uid) < 0) {
+            PLOG(ERROR) << "Failed to setfilecon " << path;
+            // TODO: include result once 25796509 is fixed
+            return 0;
+        }
+
+        if (property_get_bool("dalvik.vm.usejitprofiles")) {
+            const std::string profile_path = create_data_user_profile_package_path(userid, pkgname);
+            // read-write-execute only for the app user.
+            if (fs_prepare_dir_strict(profile_path.c_str(), 0700, uid, uid) != 0) {
+                PLOG(ERROR) << "Failed to prepare " << profile_path;
+                return -1;
+            }
+            const std::string ref_profile_path = create_data_ref_profile_package_path(pkgname);
+            // dex2oat/profman runs under the shared app gid and it needs to read/write reference
+            // profiles.
+            appid_t shared_app_gid = multiuser_get_shared_app_gid(uid);
+            if (fs_prepare_dir_strict(
+                    ref_profile_path.c_str(), 0700, shared_app_gid, shared_app_gid) != 0) {
+                PLOG(ERROR) << "Failed to prepare " << ref_profile_path;
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags) {
+    // This method only exists to upgrade system apps that have requested
+    // forceDeviceEncrypted, so their default storage always lives in a
+    // consistent location.  This only works on non-FBE devices, since we
+    // never want to risk exposing data on a device with real CE/DE storage.
+
+    auto ce_path = create_data_user_ce_package_path(uuid, userid, pkgname);
+    auto de_path = create_data_user_de_package_path(uuid, userid, pkgname);
+
+    // If neither directory is marked as default, assume CE is default
+    if (getxattr(ce_path.c_str(), kXattrDefault, nullptr, 0) == -1
+            && getxattr(de_path.c_str(), kXattrDefault, nullptr, 0) == -1) {
+        if (setxattr(ce_path.c_str(), kXattrDefault, nullptr, 0, 0) != 0) {
+            PLOG(ERROR) << "Failed to mark default storage " << ce_path;
+            return -1;
+        }
     }
 
-    std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
-    const char* pkgdir = _pkgdir.c_str();
+    // Migrate default data location if needed
+    auto target = (flags & FLAG_STORAGE_DE) ? de_path : ce_path;
+    auto source = (flags & FLAG_STORAGE_DE) ? ce_path : de_path;
 
-    if (mkdir(pkgdir, 0751) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
-        return -1;
-    }
-    if (chmod(pkgdir, 0751) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -1;
-    }
-
-    if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -1;
+    if (getxattr(target.c_str(), kXattrDefault, nullptr, 0) == -1) {
+        LOG(WARNING) << "Requested default storage " << target
+                << " is not active; migrating from " << source;
+        if (delete_dir_contents_and_dir(target) != 0) {
+            PLOG(ERROR) << "Failed to delete";
+            return -1;
+        }
+        if (rename(source.c_str(), target.c_str()) != 0) {
+            PLOG(ERROR) << "Failed to rename";
+            return -1;
+        }
     }
 
     return 0;
 }
 
-int uninstall(const char *uuid, const char *pkgname, userid_t userid)
-{
-    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
-    const char* pkgdir = _pkgdir.c_str();
-
-    remove_profile_file(pkgname);
-
-    /* delete contents AND directory, no exceptions */
-    return delete_dir_contents(pkgdir, 1, NULL);
+// Keep profile paths in sync with ActivityThread.
+constexpr const char* PRIMARY_PROFILE_NAME = "primary.prof";
+static std::string create_primary_profile(const std::string& profile_dir) {
+    return StringPrintf("%s/%s", profile_dir.c_str(), PRIMARY_PROFILE_NAME);
 }
 
-int renamepkg(const char *oldpkgname, const char *newpkgname)
-{
-    char oldpkgdir[PKG_PATH_MAX];
-    char newpkgdir[PKG_PATH_MAX];
-
-    if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
-        return -1;
-    if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
-        return -1;
-
-    if (rename(oldpkgdir, newpkgdir) < 0) {
-        ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
-        return -errno;
+static bool clear_profile(const std::string& profile) {
+    base::unique_fd ufd(open(profile.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
+    if (ufd.get() < 0) {
+        if (errno != ENOENT) {
+            PLOG(WARNING) << "Could not open profile " << profile;
+            return false;
+        } else {
+            // Nothing to clear. That's ok.
+            return true;
+        }
     }
-    return 0;
+
+    if (flock(ufd.get(), LOCK_EX | LOCK_NB) != 0) {
+        if (errno != EWOULDBLOCK) {
+            PLOG(WARNING) << "Error locking profile " << profile;
+        }
+        // This implies that the app owning this profile is running
+        // (and has acquired the lock).
+        //
+        // If we can't acquire the lock bail out since clearing is useless anyway
+        // (the app will write again to the profile).
+        //
+        // Note:
+        // This does not impact the this is not an issue for the profiling correctness.
+        // In case this is needed because of an app upgrade, profiles will still be
+        // eventually cleared by the app itself due to checksum mismatch.
+        // If this is needed because profman advised, then keeping the data around
+        // until the next run is again not an issue.
+        //
+        // If the app attempts to acquire a lock while we've held one here,
+        // it will simply skip the current write cycle.
+        return false;
+    }
+
+    bool truncated = ftruncate(ufd.get(), 0) == 0;
+    if (!truncated) {
+        PLOG(WARNING) << "Could not truncate " << profile;
+    }
+    if (flock(ufd.get(), LOCK_UN) != 0) {
+        PLOG(WARNING) << "Error unlocking profile " << profile;
+    }
+    return truncated;
 }
 
-int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid)
-{
-    struct stat s;
-
-    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
-        ALOGE("invalid uid/gid: %d %d\n", uid, gid);
-        return -1;
-    }
-
-    std::string _pkgdir(create_data_user_package_path(uuid, 0, pkgname));
-    const char* pkgdir = _pkgdir.c_str();
-
-    if (stat(pkgdir, &s) < 0) return -1;
-
-    if (s.st_uid != 0 || s.st_gid != 0) {
-        ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid);
-        return -1;
-    }
-
-    if (chmod(pkgdir, 0751) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-    if (chown(pkgdir, uid, gid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    return 0;
+static bool clear_reference_profile(const char* pkgname) {
+    std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
+    std::string reference_profile = create_primary_profile(reference_profile_dir);
+    return clear_profile(reference_profile);
 }
 
-int delete_user_data(const char *uuid, const char *pkgname, userid_t userid)
-{
-    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
-    const char* pkgdir = _pkgdir.c_str();
-
-    return delete_dir_contents(pkgdir, 0, NULL);
+static bool clear_current_profile(const char* pkgname, userid_t user) {
+    std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
+    std::string profile = create_primary_profile(profile_dir);
+    return clear_profile(profile);
 }
 
-int make_user_data(const char *uuid, const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
-{
-    std::string _pkgdir(create_data_user_package_path(uuid, userid, pkgname));
-    const char* pkgdir = _pkgdir.c_str();
-
-    if (mkdir(pkgdir, 0751) < 0) {
-        ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
-        return -errno;
+static bool clear_current_profiles(const char* pkgname) {
+    bool success = true;
+    std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
+    for (auto user : users) {
+        success &= clear_current_profile(pkgname, user);
     }
-    if (chmod(pkgdir, 0751) < 0) {
-        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
-        ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    if (chown(pkgdir, uid, uid) < 0) {
-        ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
-        unlink(pkgdir);
-        return -errno;
-    }
-
-    return 0;
+    return success;
 }
 
-int copy_complete_app(const char *from_uuid, const char *to_uuid,
-        const char *package_name, const char *data_app_name, appid_t appid,
-        const char* seinfo) {
+int clear_app_profiles(const char* pkgname) {
+    bool success = true;
+    success &= clear_reference_profile(pkgname);
+    success &= clear_current_profiles(pkgname);
+    return success ? 0 : -1;
+}
+
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+        ino_t ce_data_inode) {
+    std::string suffix = "";
+    bool only_cache = false;
+    if (flags & FLAG_CLEAR_CACHE_ONLY) {
+        suffix = CACHE_DIR_POSTFIX;
+        only_cache = true;
+    } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
+        suffix = CODE_CACHE_DIR_POSTFIX;
+        only_cache = true;
+    }
+
+    int res = 0;
+    if (flags & FLAG_STORAGE_CE) {
+        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode) + suffix;
+        if (access(path.c_str(), F_OK) == 0) {
+            res |= delete_dir_contents(path);
+        }
+    }
+    if (flags & FLAG_STORAGE_DE) {
+        auto path = create_data_user_de_package_path(uuid, userid, pkgname) + suffix;
+        if (access(path.c_str(), F_OK) == 0) {
+            // TODO: include result once 25796509 is fixed
+            delete_dir_contents(path);
+        }
+        if (!only_cache) {
+            if (!clear_current_profile(pkgname, userid)) {
+                res |= -1;
+            }
+        }
+    }
+    return res;
+}
+
+static int destroy_app_reference_profile(const char *pkgname) {
+    return delete_dir_contents_and_dir(
+        create_data_ref_profile_package_path(pkgname),
+        /*ignore_if_missing*/ true);
+}
+
+static int destroy_app_current_profiles(const char *pkgname, userid_t userid) {
+    return delete_dir_contents_and_dir(
+        create_data_user_profile_package_path(userid, pkgname),
+        /*ignore_if_missing*/ true);
+}
+
+int destroy_app_profiles(const char *pkgname) {
+    int result = 0;
+    std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
+    for (auto user : users) {
+        result |= destroy_app_current_profiles(pkgname, user);
+    }
+    result |= destroy_app_reference_profile(pkgname);
+    return result;
+}
+
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+        ino_t ce_data_inode) {
+    int res = 0;
+    if (flags & FLAG_STORAGE_CE) {
+        res |= delete_dir_contents_and_dir(
+                create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode));
+    }
+    if (flags & FLAG_STORAGE_DE) {
+        res |= delete_dir_contents_and_dir(
+                create_data_user_de_package_path(uuid, userid, pkgname));
+        destroy_app_current_profiles(pkgname, userid);
+        // TODO(calin): If the package is still installed by other users it's probably
+        // beneficial to keep the reference profile around.
+        // Verify if it's ok to do that.
+        destroy_app_reference_profile(pkgname);
+    }
+    return res;
+}
+
+int move_complete_app(const char *from_uuid, const char *to_uuid, const char *package_name,
+        const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version) {
     std::vector<userid_t> users = get_known_users(from_uuid);
 
     // Copy app
@@ -215,10 +346,11 @@
     }
 
     // Copy private data for all known users
+    // TODO: handle user_de paths
     for (auto user : users) {
-        std::string from(create_data_user_package_path(from_uuid, user, package_name));
-        std::string to(create_data_user_package_path(to_uuid, user, package_name));
-        std::string to_parent(create_data_user_path(to_uuid, user));
+        std::string from(create_data_user_ce_package_path(from_uuid, user, package_name));
+        std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
+        std::string to_parent(create_data_user_ce_path(to_uuid, user));
 
         // Data source may not exist for all users; that's okay
         if (access(from.c_str(), F_OK) != 0) {
@@ -226,14 +358,14 @@
             continue;
         }
 
-        std::string user_path(create_data_user_path(to_uuid, user));
+        std::string user_path(create_data_user_ce_path(to_uuid, user));
         if (fs_prepare_dir(user_path.c_str(), 0771, AID_SYSTEM, AID_SYSTEM) != 0) {
             LOG(ERROR) << "Failed to prepare user target " << user_path;
             goto fail;
         }
 
-        uid_t uid = multiuser_get_uid(user, appid);
-        if (make_user_data(to_uuid, package_name, uid, user, seinfo) != 0) {
+        if (create_app_data(to_uuid, package_name, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
+                appid, seinfo, target_sdk_version) != 0) {
             LOG(ERROR) << "Failed to create package target " << to;
             goto fail;
         }
@@ -257,11 +389,12 @@
                     << ": status " << rc;
             goto fail;
         }
-    }
 
-    if (restorecon_data(to_uuid, package_name, seinfo, multiuser_get_uid(0, appid)) != 0) {
-        LOG(ERROR) << "Failed to restorecon";
-        goto fail;
+        if (restorecon_app_data(to_uuid, package_name, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE,
+                appid, seinfo) != 0) {
+            LOG(ERROR) << "Failed to restorecon";
+            goto fail;
+        }
     }
 
     // We let the framework scan the new location and persist that before
@@ -278,7 +411,7 @@
         }
     }
     for (auto user : users) {
-        std::string to(create_data_user_package_path(to_uuid, user, package_name));
+        std::string to(create_data_user_ce_package_path(to_uuid, user, package_name));
         if (delete_dir_contents(to.c_str(), 1, NULL) != 0) {
             LOG(WARNING) << "Failed to rollback " << to;
         }
@@ -286,66 +419,30 @@
     return -1;
 }
 
-int make_user_config(userid_t userid)
-{
-    if (ensure_config_user_dirs(userid) == -1) {
-        return -1;
+int create_user_data(const char *uuid, userid_t userid, int user_serial ATTRIBUTE_UNUSED,
+        int flags) {
+    if (flags & FLAG_STORAGE_DE) {
+        if (uuid == nullptr) {
+            return ensure_config_user_dirs(userid);
+        }
     }
-
     return 0;
 }
 
-int delete_user(const char *uuid, userid_t userid)
-{
-    int status = 0;
-
-    std::string data_path(create_data_user_path(uuid, userid));
-    if (delete_dir_contents(data_path.c_str(), 1, NULL) != 0) {
-        status = -1;
-    }
-
-    std::string media_path(create_data_media_path(uuid, userid));
-    if (delete_dir_contents(media_path.c_str(), 1, NULL) != 0) {
-        status = -1;
-    }
-
-    // Config paths only exist on internal storage
-    if (uuid == nullptr) {
-        char config_path[PATH_MAX];
-        if ((create_user_config_path(config_path, userid) != 0)
-                || (delete_dir_contents(config_path, 1, NULL) != 0)) {
-            status = -1;
+int destroy_user_data(const char *uuid, userid_t userid, int flags) {
+    int res = 0;
+    if (flags & FLAG_STORAGE_DE) {
+        res |= delete_dir_contents_and_dir(create_data_user_de_path(uuid, userid), true);
+        if (uuid == nullptr) {
+            res |= delete_dir_contents_and_dir(create_data_misc_legacy_path(userid), true);
+            res |= delete_dir_contents_and_dir(create_data_user_profiles_path(userid), true);
         }
     }
-
-    return status;
-}
-
-int delete_cache(const char *uuid, const char *pkgname, userid_t userid)
-{
-    std::string _cachedir(
-            create_data_user_package_path(uuid, userid, pkgname) + CACHE_DIR_POSTFIX);
-    const char* cachedir = _cachedir.c_str();
-
-    /* delete contents, not the directory, no exceptions */
-    return delete_dir_contents(cachedir, 0, NULL);
-}
-
-int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid)
-{
-    std::string _codecachedir(
-            create_data_user_package_path(uuid, userid, pkgname) + CODE_CACHE_DIR_POSTFIX);
-    const char* codecachedir = _codecachedir.c_str();
-
-    struct stat s;
-
-    /* it's okay if code cache is missing */
-    if (lstat(codecachedir, &s) == -1 && errno == ENOENT) {
-        return 0;
+    if (flags & FLAG_STORAGE_CE) {
+        res |= delete_dir_contents_and_dir(create_data_user_ce_path(uuid, userid), true);
+        res |= delete_dir_contents_and_dir(create_data_media_path(uuid, userid), true);
     }
-
-    /* delete contents, not the directory, no exceptions */
-    return delete_dir_contents(codecachedir, 0, NULL);
+    return res;
 }
 
 /* Try to ensure free_size bytes of storage are available.
@@ -376,7 +473,7 @@
 
     // Special case for owner on internal storage
     if (uuid == nullptr) {
-        std::string _tmpdir(create_data_user_path(nullptr, 0));
+        std::string _tmpdir(create_data_user_ce_path(nullptr, 0));
         add_cache_files(cache, _tmpdir.c_str(), "cache");
     }
 
@@ -441,32 +538,6 @@
     return data_disk_free(data_path) >= free_size ? 0 : -1;
 }
 
-int move_dex(const char *src, const char *dst, const char *instruction_set)
-{
-    char src_dex[PKG_PATH_MAX];
-    char dst_dex[PKG_PATH_MAX];
-
-    if (validate_apk_path(src)) {
-        ALOGE("invalid apk path '%s' (bad prefix)\n", src);
-        return -1;
-    }
-    if (validate_apk_path(dst)) {
-        ALOGE("invalid apk path '%s' (bad prefix)\n", dst);
-        return -1;
-    }
-
-    if (create_cache_path(src_dex, src, instruction_set)) return -1;
-    if (create_cache_path(dst_dex, dst, instruction_set)) return -1;
-
-    ALOGV("move %s -> %s\n", src_dex, dst_dex);
-    if (rename(src_dex, dst_dex) < 0) {
-        ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
-        return -1;
-    } else {
-        return 0;
-    }
-}
-
 int rm_dex(const char *path, const char *instruction_set)
 {
     char dex_path[PKG_PATH_MAX];
@@ -476,7 +547,7 @@
         return -1;
     }
 
-    if (create_cache_path(dex_path, path, instruction_set)) return -1;
+    if (!create_cache_path(dex_path, path, instruction_set)) return -1;
 
     ALOGV("unlink %s\n", dex_path);
     if (unlink(dex_path) < 0) {
@@ -489,185 +560,101 @@
     }
 }
 
-int get_size(const char *uuid, const char *pkgname, int userid, const char *apkpath,
-             const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
-             const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
-             int64_t *_cachesize, int64_t* _asecsize)
-{
+static void add_app_data_size(std::string& path, int64_t *codesize, int64_t *datasize,
+        int64_t *cachesize) {
     DIR *d;
     int dfd;
     struct dirent *de;
     struct stat s;
-    char path[PKG_PATH_MAX];
 
-    int64_t codesize = 0;
-    int64_t datasize = 0;
-    int64_t cachesize = 0;
-    int64_t asecsize = 0;
+    d = opendir(path.c_str());
+    if (d == nullptr) {
+        PLOG(WARNING) << "Failed to open " << path;
+        return;
+    }
+    dfd = dirfd(d);
+    while ((de = readdir(d))) {
+        const char *name = de->d_name;
 
-    /* count the source apk as code -- but only if it's not
-     * on the /system partition and its not on the sdcard. */
-    if (validate_system_app_path(apkpath) &&
-            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
-        if (stat(apkpath, &s) == 0) {
-            codesize += stat_size(&s);
-            if (S_ISDIR(s.st_mode)) {
-                d = opendir(apkpath);
-                if (d != NULL) {
-                    dfd = dirfd(d);
-                    codesize += calculate_dir_size(dfd);
-                    closedir(d);
-                }
+        int64_t statsize = 0;
+        if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+            statsize = stat_size(&s);
+        }
+
+        if (de->d_type == DT_DIR) {
+            int subfd;
+            int64_t dirsize = 0;
+            /* always skip "." and ".." */
+            if (name[0] == '.') {
+                if (name[1] == 0) continue;
+                if ((name[1] == '.') && (name[2] == 0)) continue;
             }
-        }
-    }
-
-    /* count the forward locked apk as code if it is given */
-    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
-        if (stat(fwdlock_apkpath, &s) == 0) {
-            codesize += stat_size(&s);
-        }
-    }
-
-    /* count the cached dexfile as code */
-    if (!create_cache_path(path, apkpath, instruction_set)) {
-        if (stat(path, &s) == 0) {
-            codesize += stat_size(&s);
-        }
-    }
-
-    /* add in size of any libraries */
-    if (libdirpath != NULL && libdirpath[0] != '!') {
-        d = opendir(libdirpath);
-        if (d != NULL) {
-            dfd = dirfd(d);
-            codesize += calculate_dir_size(dfd);
-            closedir(d);
-        }
-    }
-
-    /* compute asec size if it is given */
-    if (asecpath != NULL && asecpath[0] != '!') {
-        if (stat(asecpath, &s) == 0) {
-            asecsize += stat_size(&s);
-        }
-    }
-
-    std::vector<userid_t> users;
-    if (userid == -1) {
-        users = get_known_users(uuid);
-    } else {
-        users.push_back(userid);
-    }
-
-    for (auto user : users) {
-        std::string _pkgdir(create_data_user_package_path(uuid, user, pkgname));
-        const char* pkgdir = _pkgdir.c_str();
-
-        d = opendir(pkgdir);
-        if (d == NULL) {
-            PLOG(WARNING) << "Failed to open " << pkgdir;
-            continue;
-        }
-        dfd = dirfd(d);
-
-        /* most stuff in the pkgdir is data, except for the "cache"
-         * directory and below, which is cache, and the "lib" directory
-         * and below, which is code...
-         */
-        while ((de = readdir(d))) {
-            const char *name = de->d_name;
-
-            if (de->d_type == DT_DIR) {
-                int subfd;
-                int64_t statsize = 0;
-                int64_t dirsize = 0;
-                    /* always skip "." and ".." */
-                if (name[0] == '.') {
-                    if (name[1] == 0) continue;
-                    if ((name[1] == '.') && (name[2] == 0)) continue;
-                }
-                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                    statsize = stat_size(&s);
-                }
-                subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
-                if (subfd >= 0) {
-                    dirsize = calculate_dir_size(subfd);
-                }
-                if(!strcmp(name,"lib")) {
-                    codesize += dirsize + statsize;
-                } else if(!strcmp(name,"cache")) {
-                    cachesize += dirsize + statsize;
-                } else {
-                    datasize += dirsize + statsize;
-                }
-            } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
-                // This is the symbolic link to the application's library
-                // code.  We'll count this as code instead of data, since
-                // it is not something that the app creates.
-                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                    codesize += stat_size(&s);
-                }
+            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+            if (subfd >= 0) {
+                dirsize = calculate_dir_size(subfd);
+                close(subfd);
+            }
+            // TODO: check xattrs!
+            if (!strcmp(name, "cache") || !strcmp(name, "code_cache")) {
+                *datasize += statsize;
+                *cachesize += dirsize;
             } else {
-                if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-                    datasize += stat_size(&s);
-                }
+                *datasize += dirsize + statsize;
             }
+        } else if (de->d_type == DT_LNK && !strcmp(name, "lib")) {
+            *codesize += statsize;
+        } else {
+            *datasize += statsize;
         }
+    }
+    closedir(d);
+}
+
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+        const char *code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+        int64_t* asecsize) {
+    DIR *d;
+    int dfd;
+
+    d = opendir(code_path);
+    if (d != nullptr) {
+        dfd = dirfd(d);
+        *codesize += calculate_dir_size(dfd);
         closedir(d);
     }
-    *_codesize = codesize;
-    *_datasize = datasize;
-    *_cachesize = cachesize;
-    *_asecsize = asecsize;
+
+    if (flags & FLAG_STORAGE_CE) {
+        auto path = create_data_user_ce_package_path(uuid, userid, pkgname, ce_data_inode);
+        add_app_data_size(path, codesize, datasize, cachesize);
+    }
+    if (flags & FLAG_STORAGE_DE) {
+        auto path = create_data_user_de_package_path(uuid, userid, pkgname);
+        add_app_data_size(path, codesize, datasize, cachesize);
+    }
+
+    *asecsize = 0;
+
     return 0;
 }
 
-int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
-{
-    char *tmp;
-    int srclen;
-    int dstlen;
-
-    srclen = strlen(src);
-
-        /* demand that we are an absolute path */
-    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
-        return -1;
-    }
-
-    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
-        return -1;
-    }
-
-    dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
-        strlen(instruction_set) +
-        strlen(DALVIK_CACHE_POSTFIX) + 2;
-
-    if (dstlen > PKG_PATH_MAX) {
-        return -1;
-    }
-
-    sprintf(path,"%s%s/%s%s",
-            DALVIK_CACHE_PREFIX,
-            instruction_set,
-            src + 1, /* skip the leading / */
-            DALVIK_CACHE_POSTFIX);
-
-    for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) {
-        if (*tmp == '/') {
-            *tmp = '@';
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode) {
+    struct stat buf;
+    memset(&buf, 0, sizeof(buf));
+    if (flags & FLAG_STORAGE_CE) {
+        auto path = create_data_user_ce_package_path(uuid, userid, pkgname);
+        if (stat(path.c_str(), &buf) == 0) {
+            *inode = buf.st_ino;
+            return 0;
         }
     }
-
-    return 0;
+    return -1;
 }
 
 static int split_count(const char *str)
 {
   char *ctx;
   int count = 0;
-  char buf[PROPERTY_VALUE_MAX];
+  char buf[kPropertyValueMax];
 
   strncpy(buf, str, sizeof(buf));
   char *pBuf = buf;
@@ -696,7 +683,7 @@
 }
 
 static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
-    const char* output_file_name, const char *pkgname __unused, const char *instruction_set)
+    const char* output_file_name, const char *pkgname ATTRIBUTE_UNUSED, const char *instruction_set)
 {
     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
@@ -735,19 +722,10 @@
     ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
 }
 
-static bool check_boolean_property(const char* property_name, bool default_value = false) {
-    char tmp_property_value[PROPERTY_VALUE_MAX];
-    bool have_property = property_get(property_name, tmp_property_value, nullptr) > 0;
-    if (!have_property) {
-        return default_value;
-    }
-    return strcmp(tmp_property_value, "true") == 0;
-}
-
-static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
-    const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
-    bool vm_safe_mode, bool debuggable, bool post_bootcomplete)
-{
+static void run_dex2oat(int zip_fd, int oat_fd, int image_fd, const char* input_file_name,
+        const char* output_file_name, int swap_fd, const char *instruction_set,
+        const char* compiler_filter, bool vm_safe_mode, bool debuggable, bool post_bootcomplete,
+        int profile_fd, const char* shared_libraries) {
     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
 
     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
@@ -756,59 +734,59 @@
         return;
     }
 
-    char prop_buf[PROPERTY_VALUE_MAX];
-    bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1');
+    char dex2oat_Xms_flag[kPropertyValueMax];
+    bool have_dex2oat_Xms_flag = get_property("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
 
-    char dex2oat_Xms_flag[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
+    char dex2oat_Xmx_flag[kPropertyValueMax];
+    bool have_dex2oat_Xmx_flag = get_property("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
 
-    char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
-
-    char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
-                                                          dex2oat_compiler_filter_flag, NULL) > 0;
-
-    char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_threads_flag = property_get(post_bootcomplete
+    char dex2oat_threads_buf[kPropertyValueMax];
+    bool have_dex2oat_threads_flag = get_property(post_bootcomplete
                                                       ? "dalvik.vm.dex2oat-threads"
                                                       : "dalvik.vm.boot-dex2oat-threads",
                                                   dex2oat_threads_buf,
                                                   NULL) > 0;
-    char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
+    char dex2oat_threads_arg[kPropertyValueMax + 2];
     if (have_dex2oat_threads_flag) {
         sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
     }
 
-    char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
+    char dex2oat_isa_features_key[kPropertyKeyMax];
     sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
-    char dex2oat_isa_features[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
+    char dex2oat_isa_features[kPropertyValueMax];
+    bool have_dex2oat_isa_features = get_property(dex2oat_isa_features_key,
                                                   dex2oat_isa_features, NULL) > 0;
 
-    char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
+    char dex2oat_isa_variant_key[kPropertyKeyMax];
     sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
-    char dex2oat_isa_variant[PROPERTY_VALUE_MAX];
-    bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key,
+    char dex2oat_isa_variant[kPropertyValueMax];
+    bool have_dex2oat_isa_variant = get_property(dex2oat_isa_variant_key,
                                                  dex2oat_isa_variant, NULL) > 0;
 
     const char *dex2oat_norelocation = "-Xnorelocate";
     bool have_dex2oat_relocation_skip_flag = false;
 
-    char dex2oat_flags[PROPERTY_VALUE_MAX];
-    int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags",
+    char dex2oat_flags[kPropertyValueMax];
+    int dex2oat_flags_count = get_property("dalvik.vm.dex2oat-flags",
                                  dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
     ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
 
     // If we booting without the real /data, don't spend time compiling.
-    char vold_decrypt[PROPERTY_VALUE_MAX];
-    bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0;
+    char vold_decrypt[kPropertyValueMax];
+    bool have_vold_decrypt = get_property("vold.decrypt", vold_decrypt, "") > 0;
     bool skip_compilation = (have_vold_decrypt &&
                              (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
                              (strcmp(vold_decrypt, "1") == 0)));
 
-    bool use_jit = check_boolean_property("debug.usejit");
-    bool generate_debug_info = check_boolean_property("debug.generate-debug-info");
+    bool generate_debug_info = property_get_bool("debug.generate-debug-info");
+
+    char app_image_format[kPropertyValueMax];
+    char image_format_arg[strlen("--image-format=") + kPropertyValueMax];
+    bool have_app_image_format =
+            image_fd >= 0 && get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
+    if (have_app_image_format) {
+        sprintf(image_format_arg, "--image-format=%s", app_image_format);
+    }
 
     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
 
@@ -821,15 +799,15 @@
     char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
     char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
-    char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX];
-    char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
-    char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
-    char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
-    char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
-    char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX];
-    char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
+    char instruction_set_variant_arg[strlen("--instruction-set-variant=") + kPropertyValueMax];
+    char instruction_set_features_arg[strlen("--instruction-set-features=") + kPropertyValueMax];
+    char dex2oat_Xms_arg[strlen("-Xms") + kPropertyValueMax];
+    char dex2oat_Xmx_arg[strlen("-Xmx") + kPropertyValueMax];
+    char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + kPropertyValueMax];
     bool have_dex2oat_swap_fd = false;
     char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN];
+    bool have_dex2oat_image_fd = false;
+    char dex2oat_image_fd[strlen("--app-image-fd=") + MAX_INT_LEN];
 
     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
@@ -842,23 +820,9 @@
         have_dex2oat_swap_fd = true;
         sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
     }
-
-    bool have_profile_file = false;
-    bool have_top_k_profile_threshold = false;
-    if (profiler && (strcmp(pkgname, "*") != 0)) {
-        char profile_file[PKG_PATH_MAX];
-        snprintf(profile_file, sizeof(profile_file), "%s/%s",
-                 DALVIK_CACHE_PREFIX "profiles", pkgname);
-        struct stat st;
-        if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) {
-            sprintf(profile_file_arg, "--profile-file=%s", profile_file);
-            have_profile_file = true;
-            if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) {
-                snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg),
-                         "--top-k-profile-threshold=%s", prop_buf);
-                have_top_k_profile_threshold = true;
-            }
-        }
+    if (image_fd >= 0) {
+        have_dex2oat_image_fd = true;
+        sprintf(dex2oat_image_fd, "--app-image-fd=%d", image_fd);
     }
 
     if (have_dex2oat_Xms_flag) {
@@ -867,6 +831,10 @@
     if (have_dex2oat_Xmx_flag) {
         sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
     }
+
+    // Compute compiler filter.
+
+    bool have_dex2oat_compiler_filter_flag;
     if (skip_compilation) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
         have_dex2oat_compiler_filter_flag = true;
@@ -874,36 +842,53 @@
     } else if (vm_safe_mode) {
         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
         have_dex2oat_compiler_filter_flag = true;
-    } else if (use_jit) {
-        strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
+    } else if (compiler_filter != nullptr &&
+            strlen(compiler_filter) + strlen("--compiler-filter=") <
+                    arraysize(dex2oat_compiler_filter_arg)) {
+        sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", compiler_filter);
         have_dex2oat_compiler_filter_flag = true;
-    } else if (have_dex2oat_compiler_filter_flag) {
-        sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
+    } else {
+        char dex2oat_compiler_filter_flag[kPropertyValueMax];
+        have_dex2oat_compiler_filter_flag = get_property("dalvik.vm.dex2oat-filter",
+                                                         dex2oat_compiler_filter_flag, NULL) > 0;
+        if (have_dex2oat_compiler_filter_flag) {
+            sprintf(dex2oat_compiler_filter_arg,
+                    "--compiler-filter=%s",
+                    dex2oat_compiler_filter_flag);
+        }
     }
 
     // Check whether all apps should be compiled debuggable.
     if (!debuggable) {
+        char prop_buf[kPropertyValueMax];
         debuggable =
-                (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
+                (get_property("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
                 (prop_buf[0] == '1');
     }
+    char profile_arg[strlen("--profile-file-fd=") + MAX_INT_LEN];
+    if (profile_fd != -1) {
+        sprintf(profile_arg, "--profile-file-fd=%d", profile_fd);
+    }
+
 
     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
 
     const char* argv[7  // program name, mandatory arguments and the final NULL
                      + (have_dex2oat_isa_variant ? 1 : 0)
                      + (have_dex2oat_isa_features ? 1 : 0)
-                     + (have_profile_file ? 1 : 0)
-                     + (have_top_k_profile_threshold ? 1 : 0)
                      + (have_dex2oat_Xms_flag ? 2 : 0)
                      + (have_dex2oat_Xmx_flag ? 2 : 0)
                      + (have_dex2oat_compiler_filter_flag ? 1 : 0)
                      + (have_dex2oat_threads_flag ? 1 : 0)
                      + (have_dex2oat_swap_fd ? 1 : 0)
+                     + (have_dex2oat_image_fd ? 1 : 0)
                      + (have_dex2oat_relocation_skip_flag ? 2 : 0)
                      + (generate_debug_info ? 1 : 0)
                      + (debuggable ? 1 : 0)
-                     + dex2oat_flags_count];
+                     + (have_app_image_format ? 1 : 0)
+                     + dex2oat_flags_count
+                     + (profile_fd == -1 ? 0 : 1)
+                     + (shared_libraries != nullptr ? 4 : 0)];
     int i = 0;
     argv[i++] = DEX2OAT_BIN;
     argv[i++] = zip_fd_arg;
@@ -917,12 +902,6 @@
     if (have_dex2oat_isa_features) {
         argv[i++] = instruction_set_features_arg;
     }
-    if (have_profile_file) {
-        argv[i++] = profile_file_arg;
-    }
-    if (have_top_k_profile_threshold) {
-        argv[i++] = top_k_profile_threshold_arg;
-    }
     if (have_dex2oat_Xms_flag) {
         argv[i++] = RUNTIME_ARG;
         argv[i++] = dex2oat_Xms_arg;
@@ -940,12 +919,18 @@
     if (have_dex2oat_swap_fd) {
         argv[i++] = dex2oat_swap_fd;
     }
+    if (have_dex2oat_image_fd) {
+        argv[i++] = dex2oat_image_fd;
+    }
     if (generate_debug_info) {
         argv[i++] = "--generate-debug-info";
     }
     if (debuggable) {
         argv[i++] = "--debuggable";
     }
+    if (have_app_image_format) {
+        argv[i++] = image_format_arg;
+    }
     if (dex2oat_flags_count) {
         i += split(dex2oat_flags, argv + i);
     }
@@ -953,6 +938,15 @@
         argv[i++] = RUNTIME_ARG;
         argv[i++] = dex2oat_norelocation;
     }
+    if (profile_fd != -1) {
+        argv[i++] = profile_arg;
+    }
+    if (shared_libraries != nullptr) {
+        argv[i++] = RUNTIME_ARG;
+        argv[i++] = "-classpath";
+        argv[i++] = RUNTIME_ARG;
+        argv[i++] = shared_libraries;
+    }
     // Do not add after dex2oat_flags, they should override others for debugging.
     argv[i] = NULL;
 
@@ -960,32 +954,6 @@
     ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
 }
 
-static int wait_child(pid_t pid)
-{
-    int status;
-    pid_t got_pid;
-
-    while (1) {
-        got_pid = waitpid(pid, &status, 0);
-        if (got_pid == -1 && errno == EINTR) {
-            printf("waitpid interrupted, retrying\n");
-        } else {
-            break;
-        }
-    }
-    if (got_pid != pid) {
-        ALOGW("waitpid failed: wanted %d, got %d: %s\n",
-            (int) pid, (int) got_pid, strerror(errno));
-        return 1;
-    }
-
-    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
-        return 0;
-    } else {
-        return status;      /* always nonzero */
-    }
-}
-
 /*
  * Whether dexopt should use a swap file when compiling an APK.
  *
@@ -1007,8 +975,8 @@
     }
 
     // Check the "override" property. If it exists, return value == "true".
-    char dex2oat_prop_buf[PROPERTY_VALUE_MAX];
-    if (property_get("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
+    char dex2oat_prop_buf[kPropertyValueMax];
+    if (get_property("dalvik.vm.dex2oat-swap", dex2oat_prop_buf, "") > 0) {
         if (strcmp(dex2oat_prop_buf, "true") == 0) {
             return true;
         } else {
@@ -1023,7 +991,7 @@
         return true;
     }
 
-    bool is_low_mem = check_boolean_property("ro.config.low_ram");
+    bool is_low_mem = property_get_bool("ro.config.low_ram");
     if (is_low_mem) {
         return true;
     }
@@ -1032,42 +1000,6 @@
     return kDefaultProvideSwapFile;
 }
 
-/*
- * Computes the odex file for the given apk_path and instruction_set.
- * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
- *
- * Returns false if it failed to determine the odex file path.
- */
-static bool calculate_odex_file_path(char path[PKG_PATH_MAX],
-                                     const char *apk_path,
-                                     const char *instruction_set)
-{
-    if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
-        + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
-      ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
-      return false;
-    }
-
-    strcpy(path, apk_path);
-    char *end = strrchr(path, '/');
-    if (end == NULL) {
-      ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
-      return false;
-    }
-    const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
-
-    strcpy(end + 1, "oat/");       // path = /system/framework/oat/\0
-    strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
-    strcat(path, apk_end);         // path = /system/framework/oat/<isa>/whatever.jar\0
-    end = strrchr(path, '.');
-    if (end == NULL) {
-      ALOGE("apk_path '%s' has no extension.\n", apk_path);
-      return false;
-    }
-    strcpy(end + 1, "odex");
-    return true;
-}
-
 static void SetDex2OatAndPatchOatScheduling(bool set_to_bg) {
     if (set_to_bg) {
         if (set_sched_policy(0, SP_BACKGROUND) < 0) {
@@ -1081,39 +1013,346 @@
     }
 }
 
-int dexopt(const char *apk_path, uid_t uid, bool is_public,
-           const char *pkgname, const char *instruction_set, int dexopt_needed,
-           bool vm_safe_mode, bool debuggable, const char* oat_dir, bool boot_complete)
-{
-    struct utimbuf ut;
-    struct stat input_stat;
-    char out_path[PKG_PATH_MAX];
-    char swap_file_name[PKG_PATH_MAX];
-    const char *input_file;
-    char in_odex_path[PKG_PATH_MAX];
-    int res, input_fd=-1, out_fd=-1, swap_fd=-1;
+static void close_all_fds(const std::vector<fd_t>& fds, const char* description) {
+    for (size_t i = 0; i < fds.size(); i++) {
+        if (close(fds[i]) != 0) {
+            PLOG(WARNING) << "Failed to close fd for " << description << " at index " << i;
+        }
+    }
+}
 
+static fd_t open_profile_dir(const std::string& profile_dir) {
+    fd_t profile_dir_fd = TEMP_FAILURE_RETRY(open(profile_dir.c_str(),
+            O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW));
+    if (profile_dir_fd < 0) {
+        // In a multi-user environment, these directories can be created at
+        // different points and it's possible we'll attempt to open a profile
+        // dir before it exists.
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "Failed to open profile_dir: " << profile_dir;
+        }
+    }
+    return profile_dir_fd;
+}
+
+static fd_t open_primary_profile_file_from_dir(const std::string& profile_dir, mode_t open_mode) {
+    fd_t profile_dir_fd  = open_profile_dir(profile_dir);
+    if (profile_dir_fd < 0) {
+        return -1;
+    }
+
+    fd_t profile_fd = -1;
+    std::string profile_file = create_primary_profile(profile_dir);
+
+    profile_fd = TEMP_FAILURE_RETRY(open(profile_file.c_str(), open_mode | O_NOFOLLOW));
+    if (profile_fd == -1) {
+        // It's not an error if the profile file does not exist.
+        if (errno != ENOENT) {
+            PLOG(ERROR) << "Failed to lstat profile_dir: " << profile_dir;
+        }
+    }
+    // TODO(calin): use AutoCloseFD instead of closing the fd manually.
+    if (close(profile_dir_fd) != 0) {
+        PLOG(WARNING) << "Could not close profile dir " << profile_dir;
+    }
+    return profile_fd;
+}
+
+static fd_t open_primary_profile_file(userid_t user, const char* pkgname) {
+    std::string profile_dir = create_data_user_profile_package_path(user, pkgname);
+    return open_primary_profile_file_from_dir(profile_dir, O_RDONLY);
+}
+
+static fd_t open_reference_profile(uid_t uid, const char* pkgname, bool read_write) {
+    std::string reference_profile_dir = create_data_ref_profile_package_path(pkgname);
+    int flags = read_write ? O_RDWR | O_CREAT : O_RDONLY;
+    fd_t fd = open_primary_profile_file_from_dir(reference_profile_dir, flags);
+    if (fd < 0) {
+        return -1;
+    }
+    if (read_write) {
+        // Fix the owner.
+        if (fchown(fd, uid, uid) < 0) {
+            close(fd);
+            return -1;
+        }
+    }
+    return fd;
+}
+
+static void open_profile_files(uid_t uid, const char* pkgname,
+            /*out*/ std::vector<fd_t>* profiles_fd, /*out*/ fd_t* reference_profile_fd) {
+    // Open the reference profile in read-write mode as profman might need to save the merge.
+    *reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ true);
+    if (*reference_profile_fd < 0) {
+        // We can't access the reference profile file.
+        return;
+    }
+
+    std::vector<userid_t> users = get_known_users(/*volume_uuid*/ nullptr);
+    for (auto user : users) {
+        fd_t profile_fd = open_primary_profile_file(user, pkgname);
+        // Add to the lists only if both fds are valid.
+        if (profile_fd >= 0) {
+            profiles_fd->push_back(profile_fd);
+        }
+    }
+}
+
+static void drop_capabilities(uid_t uid) {
+    if (setgid(uid) != 0) {
+        ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
+        exit(64);
+    }
+    if (setuid(uid) != 0) {
+        ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
+        exit(65);
+    }
+    // drop capabilities
+    struct __user_cap_header_struct capheader;
+    struct __user_cap_data_struct capdata[2];
+    memset(&capheader, 0, sizeof(capheader));
+    memset(&capdata, 0, sizeof(capdata));
+    capheader.version = _LINUX_CAPABILITY_VERSION_3;
+    if (capset(&capheader, &capdata[0]) < 0) {
+        ALOGE("capset failed: %s\n", strerror(errno));
+        exit(66);
+    }
+}
+
+static constexpr int PROFMAN_BIN_RETURN_CODE_COMPILE = 0;
+static constexpr int PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION = 1;
+static constexpr int PROFMAN_BIN_RETURN_CODE_BAD_PROFILES = 2;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
+static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
+
+static void run_profman(const std::vector<fd_t>& profiles_fd, fd_t reference_profile_fd) {
+    static const size_t MAX_INT_LEN = 32;
+    static const char* PROFMAN_BIN = "/system/bin/profman";
+
+    std::vector<std::string> profile_args(profiles_fd.size());
+    char profile_buf[strlen("--profile-file-fd=") + MAX_INT_LEN];
+    for (size_t k = 0; k < profiles_fd.size(); k++) {
+        sprintf(profile_buf, "--profile-file-fd=%d", profiles_fd[k]);
+        profile_args[k].assign(profile_buf);
+    }
+    char reference_profile_arg[strlen("--reference-profile-file-fd=") + MAX_INT_LEN];
+    sprintf(reference_profile_arg, "--reference-profile-file-fd=%d", reference_profile_fd);
+
+    // program name, reference profile fd, the final NULL and the profile fds
+    const char* argv[3 + profiles_fd.size()];
+    int i = 0;
+    argv[i++] = PROFMAN_BIN;
+    argv[i++] = reference_profile_arg;
+    for (size_t k = 0; k < profile_args.size(); k++) {
+        argv[i++] = profile_args[k].c_str();
+    }
+    // Do not add after dex2oat_flags, they should override others for debugging.
+    argv[i] = NULL;
+
+    execv(PROFMAN_BIN, (char * const *)argv);
+    ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
+    exit(68);   /* only get here on exec failure */
+}
+
+// Decides if profile guided compilation is needed or not based on existing profiles.
+// Returns true if there is enough information in the current profiles that worth
+// a re-compilation of the package.
+// If the return value is true all the current profiles would have been merged into
+// the reference profiles accessible with open_reference_profile().
+static bool analyse_profiles(uid_t uid, const char* pkgname) {
+    std::vector<fd_t> profiles_fd;
+    fd_t reference_profile_fd = -1;
+    open_profile_files(uid, pkgname, &profiles_fd, &reference_profile_fd);
+    if (profiles_fd.empty() || (reference_profile_fd == -1)) {
+        // Skip profile guided compilation because no profiles were found.
+        // Or if the reference profile info couldn't be opened.
+        close_all_fds(profiles_fd, "profiles_fd");
+        if ((reference_profile_fd != - 1) && (close(reference_profile_fd) != 0)) {
+            PLOG(WARNING) << "Failed to close fd for reference profile";
+        }
+        return false;
+    }
+
+    ALOGV("PROFMAN: --- BEGIN '%s' ---\n", pkgname);
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        /* child -- drop privileges before continuing */
+        drop_capabilities(uid);
+        run_profman(profiles_fd, reference_profile_fd);
+        exit(68);   /* only get here on exec failure */
+    }
+    /* parent */
+    int return_code = wait_child(pid);
+    bool need_to_compile = false;
+    bool should_clear_current_profiles = false;
+    bool should_clear_reference_profile = false;
+    if (!WIFEXITED(return_code)) {
+        LOG(WARNING) << "profman failed for package " << pkgname << ": " << return_code;
+    } else {
+        return_code = WEXITSTATUS(return_code);
+        switch (return_code) {
+            case PROFMAN_BIN_RETURN_CODE_COMPILE:
+                need_to_compile = true;
+                should_clear_current_profiles = true;
+                should_clear_reference_profile = false;
+                break;
+            case PROFMAN_BIN_RETURN_CODE_SKIP_COMPILATION:
+                need_to_compile = false;
+                should_clear_current_profiles = false;
+                should_clear_reference_profile = false;
+                break;
+            case PROFMAN_BIN_RETURN_CODE_BAD_PROFILES:
+                LOG(WARNING) << "Bad profiles for package " << pkgname;
+                need_to_compile = false;
+                should_clear_current_profiles = true;
+                should_clear_reference_profile = true;
+                break;
+            case PROFMAN_BIN_RETURN_CODE_ERROR_IO:  // fall-through
+            case PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING:
+                // Temporary IO problem (e.g. locking). Ignore but log a warning.
+                LOG(WARNING) << "IO error while reading profiles for package " << pkgname;
+                need_to_compile = false;
+                should_clear_current_profiles = false;
+                should_clear_reference_profile = false;
+                break;
+           default:
+                // Unknown return code or error. Unlink profiles.
+                LOG(WARNING) << "Unknown error code while processing profiles for package " << pkgname
+                        << ": " << return_code;
+                need_to_compile = false;
+                should_clear_current_profiles = true;
+                should_clear_reference_profile = true;
+                break;
+        }
+    }
+    close_all_fds(profiles_fd, "profiles_fd");
+    if (close(reference_profile_fd) != 0) {
+        PLOG(WARNING) << "Failed to close fd for reference profile";
+    }
+    if (should_clear_current_profiles) {
+        clear_current_profiles(pkgname);
+    }
+    if (should_clear_reference_profile) {
+        clear_reference_profile(pkgname);
+    }
+    return need_to_compile;
+}
+
+static void trim_extension(char* path) {
+  // Trim the extension.
+  int pos = strlen(path);
+  for (; pos >= 0 && path[pos] != '.'; --pos) {}
+  if (pos >= 0) {
+      path[pos] = '\0';  // Trim extension
+  }
+}
+
+static bool add_extension_to_file_name(char* file_name, const char* extension) {
+    if (strlen(file_name) + strlen(extension) + 1 > PKG_PATH_MAX) {
+        return false;
+    }
+    strcat(file_name, extension);
+    return true;
+}
+
+static int open_output_file(char* file_name, bool recreate, int permissions) {
+    int flags = O_RDWR | O_CREAT;
+    if (recreate) {
+        if (unlink(file_name) < 0) {
+            if (errno != ENOENT) {
+                PLOG(ERROR) << "open_output_file: Couldn't unlink " << file_name;
+            }
+        }
+        flags |= O_EXCL;
+    }
+    return open(file_name, flags, permissions);
+}
+
+static bool set_permissions_and_ownership(int fd, bool is_public, int uid, const char* path) {
+    if (fchmod(fd,
+               S_IRUSR|S_IWUSR|S_IRGRP |
+               (is_public ? S_IROTH : 0)) < 0) {
+        ALOGE("installd cannot chmod '%s' during dexopt\n", path);
+        return false;
+    } else if (fchown(fd, AID_SYSTEM, uid) < 0) {
+        ALOGE("installd cannot chown '%s' during dexopt\n", path);
+        return false;
+    }
+    return true;
+}
+
+static bool create_oat_out_path(const char* apk_path, const char* instruction_set,
+            const char* oat_dir, /*out*/ char* out_path) {
     // Early best-effort check whether we can fit the the path into our buffers.
     // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
-    // without a swap file, if necessary.
+    // without a swap file, if necessary. Reference profiles file also add an extra ".prof"
+    // extension to the cache path (5 bytes).
     if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
         ALOGE("apk_path too long '%s'\n", apk_path);
-        return -1;
+        return false;
     }
 
     if (oat_dir != NULL && oat_dir[0] != '!') {
         if (validate_apk_path(oat_dir)) {
             ALOGE("invalid oat_dir '%s'\n", oat_dir);
-            return -1;
+            return false;
         }
-        if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
-            return -1;
+        if (!calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
+            return false;
         }
     } else {
-        if (create_cache_path(out_path, apk_path, instruction_set)) {
-            return -1;
+        if (!create_cache_path(out_path, apk_path, instruction_set)) {
+            return false;
         }
     }
+    return true;
+}
+
+// TODO: Consider returning error codes.
+bool merge_profiles(uid_t uid, const char *pkgname) {
+    return analyse_profiles(uid, pkgname);
+}
+
+int dexopt(const char* apk_path, uid_t uid, const char* pkgname, const char* instruction_set,
+           int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
+           const char* volume_uuid ATTRIBUTE_UNUSED, const char* shared_libraries)
+{
+    struct utimbuf ut;
+    struct stat input_stat;
+    char out_path[PKG_PATH_MAX];
+    char swap_file_name[PKG_PATH_MAX];
+    char image_path[PKG_PATH_MAX];
+    const char *input_file;
+    char in_odex_path[PKG_PATH_MAX];
+    int res;
+    fd_t input_fd=-1, out_fd=-1, image_fd=-1, swap_fd=-1;
+    bool is_public = ((dexopt_flags & DEXOPT_PUBLIC) != 0);
+    bool vm_safe_mode = (dexopt_flags & DEXOPT_SAFEMODE) != 0;
+    bool debuggable = (dexopt_flags & DEXOPT_DEBUGGABLE) != 0;
+    bool boot_complete = (dexopt_flags & DEXOPT_BOOTCOMPLETE) != 0;
+    bool profile_guided = (dexopt_flags & DEXOPT_PROFILE_GUIDED) != 0;
+
+    CHECK(pkgname != nullptr);
+    CHECK(pkgname[0] != 0);
+
+    fd_t reference_profile_fd = -1;
+    // Public apps should not be compiled with profile information ever. Same goes for the special
+    // package '*' used for the system server.
+    if (!is_public && pkgname[0] != '*') {
+        // Open reference profile in read only mode as dex2oat does not get write permissions.
+        reference_profile_fd = open_reference_profile(uid, pkgname, /*read_write*/ false);
+        // Note: it's OK to not find a profile here.
+    }
+
+    if ((dexopt_flags & ~DEXOPT_MASK) != 0) {
+        LOG_FATAL("dexopt flags contains unknown fields\n");
+    }
+
+    if (!create_oat_out_path(apk_path, instruction_set, oat_dir, out_path)) {
+        return false;
+    }
 
     switch (dexopt_needed) {
         case DEXOPT_DEX2OAT_NEEDED:
@@ -1145,49 +1384,62 @@
         return -1;
     }
 
-    unlink(out_path);
-    out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
+    out_fd = open_output_file(out_path, /*recreate*/true, /*permissions*/0644);
     if (out_fd < 0) {
         ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
         goto fail;
     }
-    if (fchmod(out_fd,
-               S_IRUSR|S_IWUSR|S_IRGRP |
-               (is_public ? S_IROTH : 0)) < 0) {
-        ALOGE("installd cannot chmod '%s' during dexopt\n", out_path);
+    if (!set_permissions_and_ownership(out_fd, is_public, uid, out_path)) {
         goto fail;
     }
-    if (fchown(out_fd, AID_SYSTEM, uid) < 0) {
-        ALOGE("installd cannot chown '%s' during dexopt\n", out_path);
-        goto fail;
-    }
-
-    // Create profile file if there is a package name present.
-    if (strcmp(pkgname, "*") != 0) {
-        create_profile_file(pkgname, uid);
-    }
 
     // Create a swap file if necessary.
     if (ShouldUseSwapFileForDexopt()) {
         // Make sure there really is enough space.
-        size_t out_len = strlen(out_path);
-        if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) {
-            strcpy(swap_file_name, out_path);
-            strcpy(swap_file_name + strlen(out_path), ".swap");
-            unlink(swap_file_name);
-            swap_fd = open(swap_file_name, O_RDWR | O_CREAT | O_EXCL, 0600);
-            if (swap_fd < 0) {
-                // Could not create swap file. Optimistically go on and hope that we can compile
-                // without it.
-                ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
-            } else {
-                // Immediately unlink. We don't really want to hit flash.
-                unlink(swap_file_name);
-            }
-        } else {
-            // Swap file path is too long. Try to run without.
-            ALOGE("installd could not create swap file for path %s during dexopt\n", out_path);
+        strcpy(swap_file_name, out_path);
+        if (add_extension_to_file_name(swap_file_name, ".swap")) {
+            swap_fd = open_output_file(swap_file_name, /*recreate*/true, /*permissions*/0600);
         }
+        if (swap_fd < 0) {
+            // Could not create swap file. Optimistically go on and hope that we can compile
+            // without it.
+            ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
+        } else {
+            // Immediately unlink. We don't really want to hit flash.
+            if (unlink(swap_file_name) < 0) {
+                PLOG(ERROR) << "Couldn't unlink swap file " << swap_file_name;
+            }
+        }
+    }
+
+    // Avoid generating an app image for extract only since it will not contain any classes.
+    strcpy(image_path, out_path);
+    trim_extension(image_path);
+    if (add_extension_to_file_name(image_path, ".art")) {
+      char app_image_format[kPropertyValueMax];
+      bool have_app_image_format =
+              get_property("dalvik.vm.appimageformat", app_image_format, NULL) > 0;
+      // Use app images only if it is enabled (by a set image format) and we are compiling
+      // profile-guided (so the app image doesn't conservatively contain all classes).
+      if (profile_guided && have_app_image_format) {
+          // Recreate is true since we do not want to modify a mapped image. If the app is already
+          // running and we modify the image file, it can cause crashes (b/27493510).
+          image_fd = open_output_file(image_path, /*recreate*/true, /*permissions*/0600);
+          if (image_fd < 0) {
+              // Could not create application image file. Go on since we can compile without it.
+              ALOGE("installd could not create '%s' for image file during dexopt\n", image_path);
+          } else if (!set_permissions_and_ownership(image_fd, is_public, uid, image_path)) {
+              image_fd = -1;
+          }
+      }
+      // If we have a valid image file path but no image fd, erase the image file.
+      if (image_fd < 0) {
+          if (unlink(image_path) < 0) {
+              if (errno != ENOENT) {
+                  PLOG(ERROR) << "Couldn't unlink image file " << image_path;
+              }
+          }
+      }
     }
 
     ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
@@ -1196,24 +1448,8 @@
     pid = fork();
     if (pid == 0) {
         /* child -- drop privileges before continuing */
-        if (setgid(uid) != 0) {
-            ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
-            exit(64);
-        }
-        if (setuid(uid) != 0) {
-            ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
-            exit(65);
-        }
-        // drop capabilities
-        struct __user_cap_header_struct capheader;
-        struct __user_cap_data_struct capdata[2];
-        memset(&capheader, 0, sizeof(capheader));
-        memset(&capdata, 0, sizeof(capdata));
-        capheader.version = _LINUX_CAPABILITY_VERSION_3;
-        if (capset(&capheader, &capdata[0]) < 0) {
-            ALOGE("capset failed: %s\n", strerror(errno));
-            exit(66);
-        }
+        drop_capabilities(uid);
+
         SetDex2OatAndPatchOatScheduling(boot_complete);
         if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
             ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
@@ -1224,14 +1460,16 @@
             || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
             run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
         } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
+            // Pass dex2oat the relative path to the input file.
             const char *input_file_name = strrchr(input_file, '/');
             if (input_file_name == NULL) {
                 input_file_name = input_file;
             } else {
                 input_file_name++;
             }
-            run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
-                        instruction_set, vm_safe_mode, debuggable, boot_complete);
+            run_dex2oat(input_fd, out_fd, image_fd, input_file_name, out_path, swap_fd,
+                        instruction_set, compiler_filter, vm_safe_mode, debuggable, boot_complete,
+                        reference_profile_fd, shared_libraries);
         } else {
             ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
             exit(73);
@@ -1253,9 +1491,15 @@
 
     close(out_fd);
     close(input_fd);
-    if (swap_fd != -1) {
+    if (swap_fd >= 0) {
         close(swap_fd);
     }
+    if (reference_profile_fd >= 0) {
+        close(reference_profile_fd);
+    }
+    if (image_fd >= 0) {
+        close(image_fd);
+    }
     return 0;
 
 fail:
@@ -1266,13 +1510,29 @@
     if (input_fd >= 0) {
         close(input_fd);
     }
+    if (reference_profile_fd >= 0) {
+        close(reference_profile_fd);
+        // We failed to compile. Unlink the reference profile. Current profiles are already unlinked
+        // when profmoan advises compilation.
+        clear_reference_profile(pkgname);
+    }
+    if (swap_fd >= 0) {
+        close(swap_fd);
+    }
+    if (image_fd >= 0) {
+        close(image_fd);
+    }
     return -1;
 }
 
 int mark_boot_complete(const char* instruction_set)
 {
   char boot_marker_path[PKG_PATH_MAX];
-  sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set);
+  sprintf(boot_marker_path,
+          "%s/%s/%s/.booting",
+          android_data_dir.path,
+          DALVIK_CACHE,
+          instruction_set);
 
   ALOGV("mark_boot_complete : %s", boot_marker_path);
   if (unlink(boot_marker_path) != 0) {
@@ -1305,251 +1565,12 @@
     }
 }
 
-int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
-        int dstuid, int dstgid, struct stat* statbuf)
-{
-    DIR *d;
-    struct dirent *de;
-    int res;
-
-    int srcend = strlen(srcpath);
-    int dstend = strlen(dstpath);
-
-    if (lstat(srcpath, statbuf) < 0) {
-        ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
-        return 1;
-    }
-
-    if ((statbuf->st_mode&S_IFDIR) == 0) {
-        mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
-                dstuid, dstgid, statbuf);
-        ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
-        if (rename(srcpath, dstpath) >= 0) {
-            if (chown(dstpath, dstuid, dstgid) < 0) {
-                ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
-                unlink(dstpath);
-                return 1;
-            }
-        } else {
-            ALOGW("Unable to rename %s to %s: %s\n",
-                srcpath, dstpath, strerror(errno));
-            return 1;
-        }
-        return 0;
-    }
-
-    d = opendir(srcpath);
-    if (d == NULL) {
-        ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
-        return 1;
-    }
-
-    res = 0;
-
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-            /* always skip "." and ".." */
-        if (name[0] == '.') {
-            if (name[1] == 0) continue;
-            if ((name[1] == '.') && (name[2] == 0)) continue;
-        }
-
-        if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
-            ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
-            continue;
-        }
-
-        if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
-            ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
-            continue;
-        }
-
-        srcpath[srcend] = dstpath[dstend] = '/';
-        strcpy(srcpath+srcend+1, name);
-        strcpy(dstpath+dstend+1, name);
-
-        if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
-            res = 1;
-        }
-
-        // Note: we will be leaving empty directories behind in srcpath,
-        // but that is okay, the package manager will be erasing all of the
-        // data associated with .apks that disappear.
-
-        srcpath[srcend] = dstpath[dstend] = 0;
-    }
-
-    closedir(d);
-    return res;
-}
-
-int movefiles()
-{
-    DIR *d;
-    int dfd, subfd;
-    struct dirent *de;
-    struct stat s;
-    char buf[PKG_PATH_MAX+1];
-    int bufp, bufe, bufi, readlen;
-
-    char srcpkg[PKG_NAME_MAX];
-    char dstpkg[PKG_NAME_MAX];
-    char srcpath[PKG_PATH_MAX];
-    char dstpath[PKG_PATH_MAX];
-    int dstuid=-1, dstgid=-1;
-    int hasspace;
-
-    d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
-    if (d == NULL) {
-        goto done;
-    }
-    dfd = dirfd(d);
-
-        /* Iterate through all files in the directory, executing the
-         * file movements requested there-in.
-         */
-    while ((de = readdir(d))) {
-        const char *name = de->d_name;
-
-        if (de->d_type == DT_DIR) {
-            continue;
-        } else {
-            subfd = openat(dfd, name, O_RDONLY);
-            if (subfd < 0) {
-                ALOGW("Unable to open update commands at %s%s\n",
-                        UPDATE_COMMANDS_DIR_PREFIX, name);
-                continue;
-            }
-
-            bufp = 0;
-            bufe = 0;
-            buf[PKG_PATH_MAX] = 0;
-            srcpkg[0] = dstpkg[0] = 0;
-            while (1) {
-                bufi = bufp;
-                while (bufi < bufe && buf[bufi] != '\n') {
-                    bufi++;
-                }
-                if (bufi < bufe) {
-                    buf[bufi] = 0;
-                    ALOGV("Processing line: %s\n", buf+bufp);
-                    hasspace = 0;
-                    while (bufp < bufi && isspace(buf[bufp])) {
-                        hasspace = 1;
-                        bufp++;
-                    }
-                    if (buf[bufp] == '#' || bufp == bufi) {
-                        // skip comments and empty lines.
-                    } else if (hasspace) {
-                        if (dstpkg[0] == 0) {
-                            ALOGW("Path before package line in %s%s: %s\n",
-                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
-                        } else if (srcpkg[0] == 0) {
-                            // Skip -- source package no longer exists.
-                        } else {
-                            ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
-                            if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
-                                    !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
-                                movefileordir(srcpath, dstpath,
-                                        strlen(dstpath)-strlen(buf+bufp),
-                                        dstuid, dstgid, &s);
-                            }
-                        }
-                    } else {
-                        char* div = strchr(buf+bufp, ':');
-                        if (div == NULL) {
-                            ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
-                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
-                        } else {
-                            *div = 0;
-                            div++;
-                            if (strlen(buf+bufp) < PKG_NAME_MAX) {
-                                strcpy(dstpkg, buf+bufp);
-                            } else {
-                                srcpkg[0] = dstpkg[0] = 0;
-                                ALOGW("Package name too long in %s%s: %s\n",
-                                        UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
-                            }
-                            if (strlen(div) < PKG_NAME_MAX) {
-                                strcpy(srcpkg, div);
-                            } else {
-                                srcpkg[0] = dstpkg[0] = 0;
-                                ALOGW("Package name too long in %s%s: %s\n",
-                                        UPDATE_COMMANDS_DIR_PREFIX, name, div);
-                            }
-                            if (srcpkg[0] != 0) {
-                                if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
-                                    if (lstat(srcpath, &s) < 0) {
-                                        // Package no longer exists -- skip.
-                                        srcpkg[0] = 0;
-                                    }
-                                } else {
-                                    srcpkg[0] = 0;
-                                    ALOGW("Can't create path %s in %s%s\n",
-                                            div, UPDATE_COMMANDS_DIR_PREFIX, name);
-                                }
-                                if (srcpkg[0] != 0) {
-                                    if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
-                                        if (lstat(dstpath, &s) == 0) {
-                                            dstuid = s.st_uid;
-                                            dstgid = s.st_gid;
-                                        } else {
-                                            // Destination package doesn't
-                                            // exist...  due to original-package,
-                                            // this is normal, so don't be
-                                            // noisy about it.
-                                            srcpkg[0] = 0;
-                                        }
-                                    } else {
-                                        srcpkg[0] = 0;
-                                        ALOGW("Can't create path %s in %s%s\n",
-                                                div, UPDATE_COMMANDS_DIR_PREFIX, name);
-                                    }
-                                }
-                                ALOGV("Transfering from %s to %s: uid=%d\n",
-                                    srcpkg, dstpkg, dstuid);
-                            }
-                        }
-                    }
-                    bufp = bufi+1;
-                } else {
-                    if (bufp == 0) {
-                        if (bufp < bufe) {
-                            ALOGW("Line too long in %s%s, skipping: %s\n",
-                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf);
-                        }
-                    } else if (bufp < bufe) {
-                        memcpy(buf, buf+bufp, bufe-bufp);
-                        bufe -= bufp;
-                        bufp = 0;
-                    }
-                    readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
-                    if (readlen < 0) {
-                        ALOGW("Failure reading update commands in %s%s: %s\n",
-                                UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
-                        break;
-                    } else if (readlen == 0) {
-                        break;
-                    }
-                    bufe += readlen;
-                    buf[bufe] = 0;
-                    ALOGV("Read buf: %s\n", buf);
-                }
-            }
-            close(subfd);
-        }
-    }
-    closedir(d);
-done:
-    return 0;
-}
-
 int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId)
 {
     struct stat s, libStat;
     int rc = 0;
 
-    std::string _pkgdir(create_data_user_package_path(uuid, userId, pkgname));
+    std::string _pkgdir(create_data_user_ce_package_path(uuid, userId, pkgname));
     std::string _libsymlink(_pkgdir + PKG_LIB_POSTFIX);
 
     const char* pkgdir = _pkgdir.c_str();
@@ -1722,69 +1743,35 @@
     return -1;
 }
 
-int restorecon_data(const char* uuid, const char* pkgName,
-                    const char* seinfo, uid_t uid)
-{
-    struct dirent *entry;
-    DIR *d;
-    struct stat s;
-    int ret = 0;
+int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
+        appid_t appid, const char* seinfo) {
+    int res = 0;
 
     // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
-    unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
+    unsigned int seflags = SELINUX_ANDROID_RESTORECON_RECURSE;
 
     if (!pkgName || !seinfo) {
         ALOGE("Package name or seinfo tag is null when trying to restorecon.");
         return -1;
     }
 
-    // Special case for owner on internal storage
-    if (uuid == nullptr) {
-        std::string path(create_data_user_package_path(nullptr, 0, pkgName));
-
-        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, flags) < 0) {
+    uid_t uid = multiuser_get_uid(userid, appid);
+    if (flags & FLAG_STORAGE_CE) {
+        auto path = create_data_user_ce_package_path(uuid, userid, pkgName);
+        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
             PLOG(ERROR) << "restorecon failed for " << path;
-            ret |= -1;
+            res = -1;
+        }
+    }
+    if (flags & FLAG_STORAGE_DE) {
+        auto path = create_data_user_de_package_path(uuid, userid, pkgName);
+        if (selinux_android_restorecon_pkgdir(path.c_str(), seinfo, uid, seflags) < 0) {
+            PLOG(ERROR) << "restorecon failed for " << path;
+            // TODO: include result once 25796509 is fixed
         }
     }
 
-    // Relabel package directory for all secondary users.
-    std::string userdir(create_data_path(uuid) + "/" + SECONDARY_USER_PREFIX);
-    d = opendir(userdir.c_str());
-    if (d == NULL) {
-        return -1;
-    }
-
-    while ((entry = readdir(d))) {
-        if (entry->d_type != DT_DIR) {
-            continue;
-        }
-
-        const char *user = entry->d_name;
-        // Ignore "." and ".."
-        if (!strcmp(user, ".") || !strcmp(user, "..")) {
-            continue;
-        }
-
-        // user directories start with a number
-        if (user[0] < '0' || user[0] > '9') {
-            ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user);
-            continue;
-        }
-
-        std::string pkgdir(StringPrintf("%s%s/%s", userdir.c_str(), user, pkgName));
-        if (stat(pkgdir.c_str(), &s) < 0) {
-            continue;
-        }
-
-        if (selinux_android_restorecon_pkgdir(pkgdir.c_str(), seinfo, s.st_uid, flags) < 0) {
-            PLOG(ERROR) << "restorecon failed for " << pkgdir;
-            ret |= -1;
-        }
-    }
-
-    closedir(d);
-    return ret;
+    return res;
 }
 
 int create_oat_dir(const char* oat_dir, const char* instruction_set)
@@ -1843,29 +1830,84 @@
     return 0;
 }
 
-int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
-        const char *instruction_set) {
-    char *file_name_start;
-    char *file_name_end;
+// Helper for move_ab, so that we can have common failure-case cleanup.
+static bool unlink_and_rename(const char* from, const char* to) {
+    // Check whether "from" exists, and if so whether it's regular. If it is, unlink. Otherwise,
+    // return a failure.
+    struct stat s;
+    if (stat(to, &s) == 0) {
+        if (!S_ISREG(s.st_mode)) {
+            LOG(ERROR) << from << " is not a regular file to replace for A/B.";
+            return false;
+        }
+        if (unlink(to) != 0) {
+            LOG(ERROR) << "Could not unlink " << to << " to move A/B.";
+            return false;
+        }
+    } else {
+        // This may be a permission problem. We could investigate the error code, but we'll just
+        // let the rename failure do the work for us.
+    }
 
-    file_name_start = strrchr(apk_path, '/');
-    if (file_name_start == NULL) {
-         ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
+    // Try to rename "to" to "from."
+    if (rename(from, to) != 0) {
+        PLOG(ERROR) << "Could not rename " << from << " to " << to;
+        return false;
+    }
+
+    return true;
+}
+
+int move_ab(const char* apk_path, const char* instruction_set, const char* oat_dir) {
+    if (apk_path == nullptr || instruction_set == nullptr || oat_dir == nullptr) {
+        LOG(ERROR) << "Cannot move_ab with null input";
         return -1;
     }
-    file_name_end = strrchr(apk_path, '.');
-    if (file_name_end < file_name_start) {
-        ALOGE("apk_path '%s' has no extension\n", apk_path);
+    if (validate_apk_path(apk_path) != 0) {
+        LOG(ERROR) << "invalid apk_path " << apk_path;
+        return -1;
+    }
+    if (validate_apk_path(oat_dir) != 0) {
+        LOG(ERROR) << "invalid oat_dir " << oat_dir;
         return -1;
     }
 
-    // Calculate file_name
-    int file_name_len = file_name_end - file_name_start - 1;
-    char file_name[file_name_len + 1];
-    memcpy(file_name, file_name_start + 1, file_name_len);
-    file_name[file_name_len] = '\0';
+    char a_path[PKG_PATH_MAX];
+    if (!calculate_oat_file_path(a_path, oat_dir, apk_path, instruction_set)) {
+        return -1;
+    }
 
-    // <apk_parent_dir>/oat/<isa>/<file_name>.odex
-    snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
+    // B path = A path + ".b"
+    std::string b_path = StringPrintf("%s.b", a_path);
+
+    // Check whether B exists.
+    {
+        struct stat s;
+        if (stat(b_path.c_str(), &s) != 0) {
+            // Silently ignore for now. The service calling this isn't smart enough to understand
+            // lack of artifacts at the moment.
+            return -1;
+        }
+        if (!S_ISREG(s.st_mode)) {
+            LOG(ERROR) << "A/B artifact " << b_path << " is not a regular file.";
+            // Try to unlink, but swallow errors.
+            unlink(b_path.c_str());
+            return -1;
+        }
+    }
+
+    // Rename B to A.
+    if (!unlink_and_rename(b_path.c_str(), a_path)) {
+        // Delete the b_path so we don't try again (or fail earlier).
+        if (unlink(b_path.c_str()) != 0) {
+            PLOG(ERROR) << "Could not unlink " << b_path;
+        }
+
+        return -1;
+    }
+
     return 0;
 }
+
+}  // namespace installd
+}  // namespace android
diff --git a/cmds/installd/commands.h b/cmds/installd/commands.h
new file mode 100644
index 0000000..41cc209
--- /dev/null
+++ b/cmds/installd/commands.h
@@ -0,0 +1,75 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** 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.
+*/
+
+#ifndef COMMANDS_H_
+#define COMMANDS_H_
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <cutils/multiuser.h>
+
+#include <installd_constants.h>
+
+namespace android {
+namespace installd {
+
+int create_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+        appid_t appid, const char* seinfo, int target_sdk_version);
+int restorecon_app_data(const char* uuid, const char* pkgName, userid_t userid, int flags,
+        appid_t appid, const char* seinfo);
+int migrate_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags);
+int clear_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+        ino_t ce_data_inode);
+int destroy_app_data(const char *uuid, const char *pkgname, userid_t userid, int flags,
+        ino_t ce_data_inode);
+
+int move_complete_app(const char* from_uuid, const char *to_uuid, const char *package_name,
+        const char *data_app_name, appid_t appid, const char* seinfo, int target_sdk_version);
+
+int get_app_size(const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+        const char* code_path, int64_t *codesize, int64_t *datasize, int64_t *cachesize,
+        int64_t *asecsize);
+int get_app_data_inode(const char *uuid, const char *pkgname, int userid, int flags, ino_t *inode);
+
+int create_user_data(const char *uuid, userid_t userid, int user_serial, int flags);
+int destroy_user_data(const char *uuid, userid_t userid, int flags);
+
+int rm_dex(const char *path, const char *instruction_set);
+int free_cache(const char *uuid, int64_t free_size);
+
+bool merge_profiles(uid_t uid, const char *pkgname);
+
+int dexopt(const char *apk_path, uid_t uid, const char *pkgName, const char *instruction_set,
+           int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
+           const char* volume_uuid, const char* shared_libraries);
+int mark_boot_complete(const char *instruction_set);
+int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
+int idmap(const char *target_path, const char *overlay_path, uid_t uid);
+int create_oat_dir(const char* oat_dir, const char *instruction_set);
+int rm_package_dir(const char* apk_path);
+int clear_app_profiles(const char* pkgname);
+int destroy_app_profiles(const char* pkgname);
+int link_file(const char *relative_path, const char *from_base, const char *to_base);
+
+// Move a B version over to the A location. Only works for oat_dir != nullptr.
+int move_ab(const char *apk_path, const char *instruction_set, const char* oat_dir);
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // COMMANDS_H_
diff --git a/cmds/installd/file_parsing.h b/cmds/installd/file_parsing.h
new file mode 100644
index 0000000..3e2f815
--- /dev/null
+++ b/cmds/installd/file_parsing.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef OTAPREOPT_FILE_PARSING_H_
+#define OTAPREOPT_FILE_PARSING_H_
+
+#include <fstream>
+#include <functional>
+#include <string>
+
+namespace android {
+namespace installd {
+
+bool ParseFile(const std::string& strFile, std::function<bool (const std::string&)> parse) {
+    std::ifstream input_stream(strFile);
+
+    if (!input_stream.is_open()) {
+        return false;
+    }
+
+    while (!input_stream.eof()) {
+        // Read the next line.
+        std::string line;
+        getline(input_stream, line);
+
+        // Is the line empty? Simplifies the next check.
+        if (line.empty()) {
+            continue;
+        }
+
+        // Is this a comment (starts with pound)?
+        if (line[0] == '#') {
+            continue;
+        }
+
+        if (!parse(line)) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // OTAPREOPT_FILE_PARSING_H_
diff --git a/cmds/installd/globals.cpp b/cmds/installd/globals.cpp
new file mode 100644
index 0000000..6a67e29
--- /dev/null
+++ b/cmds/installd/globals.cpp
@@ -0,0 +1,138 @@
+/*
+** Copyright 2015, The Android Open Source Project
+**
+** 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 <stdlib.h>
+#include <string.h>
+
+#include <cutils/log.h>               // TODO: Move everything to base::logging.
+
+#include <globals.h>
+#include <installd_constants.h>
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
+
+namespace android {
+namespace installd {
+
+/* Directory records that are used in execution of commands. */
+dir_rec_t android_app_dir;
+dir_rec_t android_app_ephemeral_dir;
+dir_rec_t android_app_lib_dir;
+dir_rec_t android_app_private_dir;
+dir_rec_t android_asec_dir;
+dir_rec_t android_data_dir;
+dir_rec_t android_media_dir;
+dir_rec_t android_mnt_expand_dir;
+dir_rec_t android_profiles_dir;
+
+dir_rec_array_t android_system_dirs;
+
+/**
+ * Initialize all the global variables that are used elsewhere. Returns 0 upon
+ * success and -1 on error.
+ */
+void free_globals() {
+    size_t i;
+
+    for (i = 0; i < android_system_dirs.count; i++) {
+        if (android_system_dirs.dirs[i].path != NULL) {
+            free(android_system_dirs.dirs[i].path);
+        }
+    }
+
+    free(android_system_dirs.dirs);
+}
+
+bool init_globals_from_data_and_root(const char* data, const char* root) {
+    // Get the android data directory.
+    if (get_path_from_string(&android_data_dir, data) < 0) {
+        return false;
+    }
+
+    // Get the android app directory.
+    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
+        return false;
+    }
+
+    // Get the android protected app directory.
+    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
+        return false;
+    }
+
+    // Get the android ephemeral app directory.
+    if (copy_and_append(&android_app_ephemeral_dir, &android_data_dir, EPHEMERAL_APP_SUBDIR) < 0) {
+        return -1;
+    }
+
+    // Get the android app native library directory.
+    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
+        return false;
+    }
+
+    // Get the sd-card ASEC mount point.
+    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
+        return false;
+    }
+
+    // Get the android media directory.
+    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
+        return false;
+    }
+
+    // Get the android external app directory.
+    if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) {
+        return false;
+    }
+
+    // Get the android profiles directory.
+    if (copy_and_append(&android_profiles_dir, &android_data_dir, PROFILES_SUBDIR) < 0) {
+        return false;
+    }
+
+    // Take note of the system and vendor directories.
+    android_system_dirs.count = 4;
+
+    android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
+    if (android_system_dirs.dirs == NULL) {
+        ALOGE("Couldn't allocate array for dirs; aborting\n");
+        return false;
+    }
+
+    dir_rec_t android_root_dir;
+    if (get_path_from_string(&android_root_dir, root) < 0) {
+        return false;
+    }
+
+    android_system_dirs.dirs[0].path = build_string2(android_root_dir.path, APP_SUBDIR);
+    android_system_dirs.dirs[0].len = strlen(android_system_dirs.dirs[0].path);
+
+    android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
+    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
+
+    android_system_dirs.dirs[2].path = strdup("/vendor/app/");
+    android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
+
+    android_system_dirs.dirs[3].path = strdup("/oem/app/");
+    android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
+
+    return true;
+}
+
+}  // namespace installd
+}  // namespace android
diff --git a/cmds/installd/globals.h b/cmds/installd/globals.h
new file mode 100644
index 0000000..3e52346
--- /dev/null
+++ b/cmds/installd/globals.h
@@ -0,0 +1,56 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** 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.
+*/
+
+#ifndef GLOBALS_H_
+#define GLOBALS_H_
+
+#include <inttypes.h>
+
+namespace android {
+namespace installd {
+
+/* data structures */
+
+struct dir_rec_t {
+    char* path;
+    size_t len;
+};
+
+struct dir_rec_array_t {
+    size_t count;
+    dir_rec_t* dirs;
+};
+
+extern dir_rec_t android_app_dir;
+extern dir_rec_t android_app_ephemeral_dir;
+extern dir_rec_t android_app_lib_dir;
+extern dir_rec_t android_app_private_dir;
+extern dir_rec_t android_asec_dir;
+extern dir_rec_t android_data_dir;
+extern dir_rec_t android_media_dir;
+extern dir_rec_t android_mnt_expand_dir;
+extern dir_rec_t android_profiles_dir;
+
+extern dir_rec_array_t android_system_dirs;
+
+void free_globals();
+bool init_globals_from_data_and_root(const char* data, const char* root);
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // GLOBALS_H_
diff --git a/cmds/installd/installd.cpp b/cmds/installd/installd.cpp
index f67e838..e8fce91 100644
--- a/cmds/installd/installd.cpp
+++ b/cmds/installd/installd.cpp
@@ -14,19 +14,167 @@
 ** limitations under the License.
 */
 
-#include "installd.h"
-
-#include <base/logging.h>
-
-#include <sys/capability.h>
-#include <sys/prctl.h>
+#include <fcntl.h>
 #include <selinux/android.h>
 #include <selinux/avc.h>
+#include <sys/capability.h>
+#include <sys/fsuid.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <android-base/logging.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>               // TODO: Move everything to base::logging.
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include <private/android_filesystem_config.h>
+
+#include <commands.h>
+#include <globals.h>
+#include <installd_constants.h>
+#include <installd_deps.h>  // Need to fill in requirements of commands.
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
+#define SOCKET_PATH "installd"
 
 #define BUFFER_MAX    1024  /* input buffer for commands */
 #define TOKEN_MAX     16    /* max number of arguments in buffer */
 #define REPLY_MAX     256   /* largest reply allowed */
 
+namespace android {
+namespace installd {
+
+// Check that installd-deps sizes match cutils sizes.
+static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
+static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
+
+////////////////////////
+// Plug-in functions. //
+////////////////////////
+
+int get_property(const char *key, char *value, const char *default_value) {
+    return property_get(key, value, default_value);
+}
+
+// Compute the output path of
+bool calculate_oat_file_path(char path[PKG_PATH_MAX],
+                             const char *oat_dir,
+                             const char *apk_path,
+                             const char *instruction_set) {
+    char *file_name_start;
+    char *file_name_end;
+
+    file_name_start = strrchr(apk_path, '/');
+    if (file_name_start == NULL) {
+        ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
+        return false;
+    }
+    file_name_end = strrchr(apk_path, '.');
+    if (file_name_end < file_name_start) {
+        ALOGE("apk_path '%s' has no extension\n", apk_path);
+        return false;
+    }
+
+    // Calculate file_name
+    int file_name_len = file_name_end - file_name_start - 1;
+    char file_name[file_name_len + 1];
+    memcpy(file_name, file_name_start + 1, file_name_len);
+    file_name[file_name_len] = '\0';
+
+    // <apk_parent_dir>/oat/<isa>/<file_name>.odex
+    snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
+    return true;
+}
+
+/*
+ * Computes the odex file for the given apk_path and instruction_set.
+ * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
+ *
+ * Returns false if it failed to determine the odex file path.
+ */
+bool calculate_odex_file_path(char path[PKG_PATH_MAX],
+                              const char *apk_path,
+                              const char *instruction_set) {
+    if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
+            + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
+        ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
+        return false;
+    }
+
+    strcpy(path, apk_path);
+    char *end = strrchr(path, '/');
+    if (end == NULL) {
+        ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+        return false;
+    }
+    const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
+
+    strcpy(end + 1, "oat/");       // path = /system/framework/oat/\0
+    strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
+    strcat(path, apk_end);         // path = /system/framework/oat/<isa>/whatever.jar\0
+    end = strrchr(path, '.');
+    if (end == NULL) {
+        ALOGE("apk_path '%s' has no extension.\n", apk_path);
+        return false;
+    }
+    strcpy(end + 1, "odex");
+    return true;
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX],
+                       const char *src,
+                       const char *instruction_set) {
+    /* demand that we are an absolute path */
+    if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) {
+        return false;
+    }
+
+    size_t srclen = strlen(src);
+
+    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
+        return false;
+    }
+
+    size_t dstlen =
+        android_data_dir.len +
+        strlen(DALVIK_CACHE) +
+        1 +
+        strlen(instruction_set) +
+        srclen +
+        strlen(DALVIK_CACHE_POSTFIX) + 2;
+
+    if (dstlen > PKG_PATH_MAX) {
+        return false;
+    }
+
+    sprintf(path,"%s%s/%s/%s%s",
+            android_data_dir.path,
+            DALVIK_CACHE,
+            instruction_set,
+            src + 1, /* skip the leading / */
+            DALVIK_CACHE_POSTFIX);
+
+    char* tmp =
+            path +
+            android_data_dir.len +
+            strlen(DALVIK_CACHE) +
+            1 +
+            strlen(instruction_set) + 1;
+
+    for(; *tmp; tmp++) {
+        if (*tmp == '/') {
+            *tmp = '@';
+        }
+    }
+
+    return true;
+}
+
+
 static char* parse_null(char* arg) {
     if (strcmp(arg, "!") == 0) {
         return nullptr;
@@ -35,80 +183,131 @@
     }
 }
 
-static int do_ping(char **arg __unused, char reply[REPLY_MAX] __unused)
+static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     return 0;
 }
 
-static int do_install(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return install(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); /* uuid, pkgname, uid, gid, seinfo */
+static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    /* const char *uuid, const char *pkgname, userid_t userid, int flags,
+            appid_t appid, const char* seinfo, int target_sdk_version */
+    return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]),
+                           atoi(arg[4]), arg[5], atoi(arg[6]));
 }
 
-static int do_dexopt(char **arg, char reply[REPLY_MAX] __unused)
-{
-    /* apk_path, uid, is_public, pkgname, instruction_set,
-     * dexopt_needed, vm_safe_mode, debuggable, oat_dir, boot_complete */
-    return dexopt(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3], arg[4], atoi(arg[5]),
-                  atoi(arg[6]), atoi(arg[7]), arg[8], atoi(arg[9]));
+static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    /* const char* uuid, const char* pkgName, userid_t userid, int flags,
+            appid_t appid, const char* seinfo */
+    return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]);
 }
 
-static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] __unused)
+static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    /* const char *uuid, const char *pkgname, userid_t userid, int flags */
+    return migrate_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
+}
+
+static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+    return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
+}
+
+static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
+    return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
+}
+
+// We use otapreopt_chroot to get into the chroot.
+static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot";
+
+static int do_ota_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    // Time to fork and run otapreopt.
+
+    // Check that the tool exists.
+    struct stat s;
+    if (stat(kOtaPreopt, &s) != 0) {
+        LOG(ERROR) << "Otapreopt chroot tool not found.";
+        return -1;
+    }
+
+    pid_t pid = fork();
+    if (pid == 0) {
+        const char* argv[1 + 9 + 1];
+        argv[0] = kOtaPreopt;
+        for (size_t i = 1; i <= 9; ++i) {
+            argv[i] = arg[i - 1];
+        }
+        argv[10] = nullptr;
+
+        execv(argv[0], (char * const *)argv);
+        PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed";
+        exit(99);
+    } else {
+        int res = wait_child(pid);
+        if (res == 0) {
+            ALOGV("DexInv: --- END OTAPREOPT (success) ---\n");
+        } else {
+            ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res);
+        }
+        return res;
+    }
+}
+
+static int do_dexopt(char **arg, char reply[REPLY_MAX])
+{
+    int dexopt_flags = atoi(arg[6]);
+    if ((dexopt_flags & DEXOPT_OTA) != 0) {
+      return do_ota_dexopt(arg, reply);
+    }
+    return dexopt(arg[0],                      // apk_path
+                  atoi(arg[1]),                // uid
+                  arg[2],                      // pkgname
+                  arg[3],                      // instruction_set
+                  atoi(arg[4]),                // dexopt_needed
+                  arg[5],                      // oat_dir
+                  dexopt_flags,
+                  arg[7],                      // compiler_filter
+                  parse_null(arg[8]),          // volume_uuid
+                  parse_null(arg[9]));         // shared_libraries
+}
+
+static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
+{
+    uid_t uid = static_cast<uid_t>(atoi(arg[0]));
+    const char* pkgname = arg[1];
+    if (merge_profiles(uid, pkgname)) {
+        strncpy(reply, "true", REPLY_MAX);
+    } else {
+        strncpy(reply, "false", REPLY_MAX);
+    }
+    return 0;
+}
+
+static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     return mark_boot_complete(arg[0] /* instruction set */);
 }
 
-static int do_move_dex(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */
-}
-
-static int do_rm_dex(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
 }
 
-static int do_remove(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return uninstall(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
-}
-
-static int do_rename(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return renamepkg(arg[0], arg[1]); /* oldpkgname, newpkgname */
-}
-
-static int do_fixuid(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return fix_uid(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */
-}
-
-static int do_free_cache(char **arg, char reply[REPLY_MAX] __unused) /* TODO int:free_size */
+static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
 {
     return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
 }
 
-static int do_rm_cache(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return delete_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
-}
-
-static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return delete_code_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
-}
-
-static int do_get_size(char **arg, char reply[REPLY_MAX])
-{
+static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
     int64_t codesize = 0;
     int64_t datasize = 0;
     int64_t cachesize = 0;
     int64_t asecsize = 0;
     int res = 0;
 
-        /* uuid, pkgdir, userid, apkpath */
-    res = get_size(parse_null(arg[0]), arg[1], atoi(arg[2]), arg[3], arg[4], arg[5], arg[6],
-            arg[7], &codesize, &datasize, &cachesize, &asecsize);
+    /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
+            const char* code_path */
+    res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
+            arg[5], &codesize, &datasize, &cachesize, &asecsize);
 
     /*
      * Each int64_t can take up 22 characters printed out. Make sure it
@@ -119,72 +318,82 @@
     return res;
 }
 
-static int do_rm_user_data(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
+static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
+    ino_t inode = 0;
+    int res = 0;
+
+    /* const char *uuid, const char *pkgname, int userid, int flags */
+    res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
+
+    snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
+    return res;
 }
 
-static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] __unused)
-{
-    // from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
-    return copy_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
+static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    /* const char* from_uuid, const char *to_uuid, const char *package_name,
+            const char *data_app_name, appid_t appid, const char* seinfo,
+            int target_sdk_version */
+    return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3],
+                             atoi(arg[4]), arg[5], atoi(arg[6]));
 }
 
-static int do_mk_user_data(char **arg, char reply[REPLY_MAX] __unused)
+static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]);
-                             /* uuid, pkgname, uid, userid, seinfo */
+    /* const char *uuid, userid_t userid, int user_serial, int flags */
+    return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
 }
 
-static int do_mk_user_config(char **arg, char reply[REPLY_MAX] __unused)
+static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
-    return make_user_config(atoi(arg[0])); /* userid */
+    /* const char *uuid, userid_t userid, int flags */
+    return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
 }
 
-static int do_rm_user(char **arg, char reply[REPLY_MAX] __unused)
-{
-    return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
-}
-
-static int do_movefiles(char **arg __unused, char reply[REPLY_MAX] __unused)
-{
-    return movefiles();
-}
-
-static int do_linklib(char **arg, char reply[REPLY_MAX] __unused)
+static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
 }
 
-static int do_idmap(char **arg, char reply[REPLY_MAX] __unused)
+static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     return idmap(arg[0], arg[1], atoi(arg[2]));
 }
 
-static int do_restorecon_data(char **arg, char reply[REPLY_MAX] __attribute__((unused)))
-{
-    return restorecon_data(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
-                             /* uuid, pkgName, seinfo, uid*/
-}
-
-static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] __unused)
+static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     /* oat_dir, instruction_set */
     return create_oat_dir(arg[0], arg[1]);
 }
 
-static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] __unused)
+static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     /* oat_dir */
     return rm_package_dir(arg[0]);
 }
 
-static int do_link_file(char **arg, char reply[REPLY_MAX] __unused)
+static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+{
+    /* package_name */
+    return clear_app_profiles(arg[0]);
+}
+
+static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
+{
+    /* package_name */
+    return destroy_app_profiles(arg[0]);
+}
+
+static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
 {
     /* relative_path, from_base, to_base */
     return link_file(arg[0], arg[1], arg[2]);
 }
 
+static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
+    // apk_path, instruction_set, oat_dir
+    return move_ab(arg[0], arg[1], arg[2]);
+}
+
 struct cmdinfo {
     const char *name;
     unsigned numargs;
@@ -193,30 +402,32 @@
 
 struct cmdinfo cmds[] = {
     { "ping",                 0, do_ping },
-    { "install",              5, do_install },
-    { "dexopt",               10, do_dexopt },
+
+    { "create_app_data",      7, do_create_app_data },
+    { "restorecon_app_data",  6, do_restorecon_app_data },
+    { "migrate_app_data",     4, do_migrate_app_data },
+    { "clear_app_data",       5, do_clear_app_data },
+    { "destroy_app_data",     5, do_destroy_app_data },
+    { "move_complete_app",    7, do_move_complete_app },
+    { "get_app_size",         6, do_get_app_size },
+    { "get_app_data_inode",   4, do_get_app_data_inode },
+
+    { "create_user_data",     4, do_create_user_data },
+    { "destroy_user_data",    3, do_destroy_user_data },
+
+    { "dexopt",              10, do_dexopt },
     { "markbootcomplete",     1, do_mark_boot_complete },
-    { "movedex",              3, do_move_dex },
     { "rmdex",                2, do_rm_dex },
-    { "remove",               3, do_remove },
-    { "rename",               2, do_rename },
-    { "fixuid",               4, do_fixuid },
     { "freecache",            2, do_free_cache },
-    { "rmcache",              3, do_rm_cache },
-    { "rmcodecache",          3, do_rm_code_cache },
-    { "getsize",              8, do_get_size },
-    { "rmuserdata",           3, do_rm_user_data },
-    { "cpcompleteapp",        6, do_cp_complete_app },
-    { "movefiles",            0, do_movefiles },
     { "linklib",              4, do_linklib },
-    { "mkuserdata",           5, do_mk_user_data },
-    { "mkuserconfig",         1, do_mk_user_config },
-    { "rmuser",               2, do_rm_user },
     { "idmap",                3, do_idmap },
-    { "restorecondata",       4, do_restorecon_data },
     { "createoatdir",         2, do_create_oat_dir },
     { "rmpackagedir",         1, do_rm_package_dir },
-    { "linkfile",             3, do_link_file }
+    { "clear_app_profiles",   1, do_clear_app_profiles },
+    { "destroy_app_profiles", 1, do_destroy_app_profiles },
+    { "linkfile",             3, do_link_file },
+    { "move_ab",              3, do_move_ab },
+    { "merge_profiles",       2, do_merge_profiles },
 };
 
 static int readx(int s, void *_buf, int count)
@@ -321,89 +532,22 @@
     return 0;
 }
 
-/**
- * Initialize all the global variables that are used elsewhere. Returns 0 upon
- * success and -1 on error.
- */
-void free_globals() {
-    size_t i;
-
-    for (i = 0; i < android_system_dirs.count; i++) {
-        if (android_system_dirs.dirs[i].path != NULL) {
-            free(android_system_dirs.dirs[i].path);
-        }
+bool initialize_globals() {
+    const char* data_path = getenv("ANDROID_DATA");
+    if (data_path == nullptr) {
+        ALOGE("Could not find ANDROID_DATA");
+        return false;
+    }
+    const char* root_path = getenv("ANDROID_ROOT");
+    if (root_path == nullptr) {
+        ALOGE("Could not find ANDROID_ROOT");
+        return false;
     }
 
-    free(android_system_dirs.dirs);
+    return init_globals_from_data_and_root(data_path, root_path);
 }
 
-int initialize_globals() {
-    // Get the android data directory.
-    if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) {
-        return -1;
-    }
-
-    // Get the android app directory.
-    if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the android protected app directory.
-    if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the android app native library directory.
-    if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the sd-card ASEC mount point.
-    if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) {
-        return -1;
-    }
-
-    // Get the android media directory.
-    if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) {
-        return -1;
-    }
-
-    // Get the android external app directory.
-    if (get_path_from_string(&android_mnt_expand_dir, "/mnt/expand/") < 0) {
-        return -1;
-    }
-
-    // Take note of the system and vendor directories.
-    android_system_dirs.count = 4;
-
-    android_system_dirs.dirs = (dir_rec_t*) calloc(android_system_dirs.count, sizeof(dir_rec_t));
-    if (android_system_dirs.dirs == NULL) {
-        ALOGE("Couldn't allocate array for dirs; aborting\n");
-        return -1;
-    }
-
-    dir_rec_t android_root_dir;
-    if (get_path_from_env(&android_root_dir, "ANDROID_ROOT") < 0) {
-        ALOGE("Missing ANDROID_ROOT; aborting\n");
-        return -1;
-    }
-
-    android_system_dirs.dirs[0].path = build_string2(android_root_dir.path, APP_SUBDIR);
-    android_system_dirs.dirs[0].len = strlen(android_system_dirs.dirs[0].path);
-
-    android_system_dirs.dirs[1].path = build_string2(android_root_dir.path, PRIV_APP_SUBDIR);
-    android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path);
-
-    android_system_dirs.dirs[2].path = strdup("/vendor/app/");
-    android_system_dirs.dirs[2].len = strlen(android_system_dirs.dirs[2].path);
-
-    android_system_dirs.dirs[3].path = strdup("/oem/app/");
-    android_system_dirs.dirs[3].len = strlen(android_system_dirs.dirs[3].path);
-
-    return 0;
-}
-
-int initialize_directories() {
+static int initialize_directories() {
     int res = -1;
 
     // Read current filesystem layout version to handle upgrade paths
@@ -416,139 +560,11 @@
     }
     int version = oldVersion;
 
-    // /data/user
-    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
-    // /data/data
-    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
-    // /data/user/0
-    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
-    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
-        goto fail;
-    }
-
-    // Make the /data/user directory if necessary
-    if (access(user_data_dir, R_OK) < 0) {
-        if (mkdir(user_data_dir, 0711) < 0) {
-            goto fail;
-        }
-        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
-            goto fail;
-        }
-        if (chmod(user_data_dir, 0711) < 0) {
-            goto fail;
-        }
-    }
-    // Make the /data/user/0 symlink to /data/data if necessary
-    if (access(primary_data_dir, R_OK) < 0) {
-        if (symlink(legacy_data_dir, primary_data_dir)) {
-            goto fail;
-        }
-    }
-
-    if (version == 0) {
-        // Introducing multi-user, so migrate /data/media contents into /data/media/0
-        ALOGD("Upgrading /data/media for multi-user");
-
-        // Ensure /data/media
-        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-            goto fail;
-        }
-
-        // /data/media.tmp
-        char media_tmp_dir[PATH_MAX];
-        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
-
-        // Only copy when upgrade not already in progress
-        if (access(media_tmp_dir, F_OK) == -1) {
-            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
-                ALOGE("Failed to move legacy media path: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        // Create /data/media again
-        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-            goto fail;
-        }
-
-        if (selinux_android_restorecon(android_media_dir.path, 0)) {
-            goto fail;
-        }
-
-        // /data/media/0
-        char owner_media_dir[PATH_MAX];
-        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
-
-        // Move any owner data into place
-        if (access(media_tmp_dir, F_OK) == 0) {
-            if (rename(media_tmp_dir, owner_media_dir) == -1) {
-                ALOGE("Failed to move owner media path: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
-        // Ensure media directories for any existing users
-        DIR *dir;
-        struct dirent *dirent;
-        char user_media_dir[PATH_MAX];
-
-        dir = opendir(user_data_dir);
-        if (dir != NULL) {
-            while ((dirent = readdir(dir))) {
-                if (dirent->d_type == DT_DIR) {
-                    const char *name = dirent->d_name;
-
-                    // skip "." and ".."
-                    if (name[0] == '.') {
-                        if (name[1] == 0) continue;
-                        if ((name[1] == '.') && (name[2] == 0)) continue;
-                    }
-
-                    // /data/media/<user_id>
-                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
-                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-                        goto fail;
-                    }
-                }
-            }
-            closedir(dir);
-        }
-
-        version = 1;
-    }
-
-    // /data/media/obb
-    char media_obb_dir[PATH_MAX];
-    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
-
-    if (version == 1) {
-        // Introducing /data/media/obb for sharing OBB across users; migrate
-        // any existing OBB files from owner.
-        ALOGD("Upgrading to shared /data/media/obb");
-
-        // /data/media/0/Android/obb
-        char owner_obb_path[PATH_MAX];
-        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
-
-        // Only move if target doesn't already exist
-        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
-            if (rename(owner_obb_path, media_obb_dir) == -1) {
-                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
-                goto fail;
-            }
-        }
-
+    if (version < 2) {
+        SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
         version = 2;
     }
 
-    if (ensure_media_user_dirs(nullptr, 0) == -1) {
-        ALOGE("Failed to setup media for user 0");
-        goto fail;
-    }
-    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-        goto fail;
-    }
-
     if (ensure_config_user_dirs(0) == -1) {
         ALOGE("Failed to setup misc for user 0");
         goto fail;
@@ -568,7 +584,7 @@
 
         DIR *dir;
         struct dirent *dirent;
-        dir = opendir(user_data_dir);
+        dir = opendir("/data/user");
         if (dir != NULL) {
             while ((dirent = readdir(dir))) {
                 const char *name = dirent->d_name;
@@ -630,9 +646,6 @@
     res = 0;
 
 fail:
-    free(user_data_dir);
-    free(legacy_data_dir);
-    free(primary_data_dir);
     return res;
 }
 
@@ -657,7 +670,7 @@
     return 0;
 }
 
-int main(const int argc __unused, char *argv[]) {
+static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
     char buf[BUFFER_MAX];
     struct sockaddr addr;
     socklen_t alen;
@@ -673,7 +686,7 @@
     cb.func_log = log_callback;
     selinux_set_callback(SELINUX_CB_LOG, cb);
 
-    if (initialize_globals() < 0) {
+    if (!initialize_globals()) {
         ALOGE("Could not initialize globals; exiting.\n");
         exit(1);
     }
@@ -735,3 +748,10 @@
 
     return 0;
 }
+
+}  // namespace installd
+}  // namespace android
+
+int main(const int argc, char *argv[]) {
+    return android::installd::installd_main(argc, argv);
+}
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
deleted file mode 100644
index 24b9084..0000000
--- a/cmds/installd/installd.h
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** 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.
-*/
-
-#define LOG_TAG "installd"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <inttypes.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <utime.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <string>
-#include <vector>
-
-#include <cutils/fs.h>
-#include <cutils/sockets.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-#include <cutils/multiuser.h>
-
-#include <private/android_filesystem_config.h>
-
-#if defined(__APPLE__)
-#include <sys/mount.h>
-#else
-#include <sys/statfs.h>
-#endif
-
-#define SOCKET_PATH "installd"
-
-
-/* elements combined with a valid package name to form paths */
-
-#define PRIMARY_USER_PREFIX    "data/"
-#define SECONDARY_USER_PREFIX  "user/"
-
-#define PKG_DIR_POSTFIX        ""
-
-#define PKG_LIB_POSTFIX        "/lib"
-
-#define CACHE_DIR_POSTFIX      "/cache"
-#define CODE_CACHE_DIR_POSTFIX "/code_cache"
-
-#define APP_SUBDIR             "app/" // sub-directory under ANDROID_DATA
-#define PRIV_APP_SUBDIR        "priv-app/" // sub-directory under ANDROID_DATA
-
-#define APP_LIB_SUBDIR         "app-lib/" // sub-directory under ANDROID_DATA
-
-#define MEDIA_SUBDIR           "media/" // sub-directory under ANDROID_DATA
-
-/* other handy constants */
-
-#define PRIVATE_APP_SUBDIR     "app-private/" // sub-directory under ANDROID_DATA
-
-#define DALVIK_CACHE_PREFIX    "/data/dalvik-cache/"
-#define DALVIK_CACHE_POSTFIX   "/classes.dex"
-
-#define UPDATE_COMMANDS_DIR_PREFIX  "/system/etc/updatecmds/"
-
-#define IDMAP_PREFIX           "/data/resource-cache/"
-#define IDMAP_SUFFIX           "@idmap"
-
-#define PKG_NAME_MAX  128   /* largest allowed package name */
-#define PKG_PATH_MAX  256   /* max size of any path we use */
-
-/* dexopt needed flags matching those in dalvik.system.DexFile */
-#define DEXOPT_DEX2OAT_NEEDED        1
-#define DEXOPT_PATCHOAT_NEEDED       2
-#define DEXOPT_SELF_PATCHOAT_NEEDED  3
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
-
-/* data structures */
-
-typedef struct {
-    char* path;
-    size_t len;
-} dir_rec_t;
-
-typedef struct {
-    size_t count;
-    dir_rec_t* dirs;
-} dir_rec_array_t;
-
-extern dir_rec_t android_app_dir;
-extern dir_rec_t android_app_private_dir;
-extern dir_rec_t android_app_lib_dir;
-extern dir_rec_t android_data_dir;
-extern dir_rec_t android_asec_dir;
-extern dir_rec_t android_media_dir;
-extern dir_rec_t android_mnt_expand_dir;
-extern dir_rec_array_t android_system_dirs;
-
-typedef struct cache_dir_struct {
-    struct cache_dir_struct* parent;
-    int32_t childCount;
-    int32_t hiddenCount;
-    int32_t deleted;
-    char name[];
-} cache_dir_t;
-
-typedef struct {
-    cache_dir_t* dir;
-    time_t modTime;
-    char name[];
-} cache_file_t;
-
-typedef struct {
-    size_t numDirs;
-    size_t availDirs;
-    cache_dir_t** dirs;
-    size_t numFiles;
-    size_t availFiles;
-    cache_file_t** files;
-    size_t numCollected;
-    void* memBlocks;
-    int8_t* curMemBlockAvail;
-    int8_t* curMemBlockEnd;
-} cache_t;
-
-/* util.c */
-
-int create_pkg_path(char path[PKG_PATH_MAX],
-                    const char *pkgname,
-                    const char *postfix,
-                    userid_t userid);
-
-std::string create_data_path(const char* volume_uuid);
-
-std::string create_data_app_path(const char* volume_uuid);
-
-std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
-
-std::string create_data_user_path(const char* volume_uuid, userid_t userid);
-
-std::string create_data_user_package_path(const char* volume_uuid,
-        userid_t user, const char* package_name);
-
-std::string create_data_media_path(const char* volume_uuid, userid_t userid);
-
-std::vector<userid_t> get_known_users(const char* volume_uuid);
-
-int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);
-
-int create_move_path(char path[PKG_PATH_MAX],
-                     const char* pkgname,
-                     const char* leaf,
-                     userid_t userid);
-
-int is_valid_package_name(const char* pkgname);
-
-int create_cache_path(char path[PKG_PATH_MAX], const char *src,
-                      const char *instruction_set);
-
-int delete_dir_contents(const char *pathname,
-                        int also_delete_dir,
-                        int (*exclusion_predicate)(const char *name, const int is_dir));
-
-int delete_dir_contents_fd(int dfd, const char *name);
-
-int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t group);
-
-int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
-
-int64_t data_disk_free(const std::string& data_path);
-
-cache_t* start_cache_collection();
-
-void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
-
-void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size);
-
-void finish_cache_collection(cache_t* cache);
-
-int validate_system_app_path(const char* path);
-
-int get_path_from_env(dir_rec_t* rec, const char* var);
-
-int get_path_from_string(dir_rec_t* rec, const char* path);
-
-int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
-
-int validate_apk_path(const char *path);
-int validate_apk_path_subdirs(const char *path);
-
-int append_and_increment(char** dst, const char* src, size_t* dst_size);
-
-char *build_string2(const char *s1, const char *s2);
-char *build_string3(const char *s1, const char *s2, const char *s3);
-
-int ensure_dir(const char* path, mode_t mode, uid_t uid, gid_t gid);
-int ensure_media_user_dirs(const char* uuid, userid_t userid);
-int ensure_config_user_dirs(userid_t userid);
-int create_profile_file(const char *pkgname, gid_t gid);
-void remove_profile_file(const char *pkgname);
-
-/* commands.c */
-
-int install(const char *uuid, const char *pkgname, uid_t uid, gid_t gid, const char *seinfo);
-int uninstall(const char *uuid, const char *pkgname, userid_t userid);
-int renamepkg(const char *oldpkgname, const char *newpkgname);
-int fix_uid(const char *uuid, const char *pkgname, uid_t uid, gid_t gid);
-int delete_user_data(const char *uuid, const char *pkgname, userid_t userid);
-int make_user_data(const char *uuid, const char *pkgname, uid_t uid,
-        userid_t userid, const char* seinfo);
-int copy_complete_app(const char* from_uuid, const char *to_uuid,
-        const char *package_name, const char *data_app_name, appid_t appid,
-        const char* seinfo);
-int make_user_config(userid_t userid);
-int delete_user(const char *uuid, userid_t userid);
-int delete_cache(const char *uuid, const char *pkgname, userid_t userid);
-int delete_code_cache(const char *uuid, const char *pkgname, userid_t userid);
-int move_dex(const char *src, const char *dst, const char *instruction_set);
-int rm_dex(const char *path, const char *instruction_set);
-int protect(char *pkgname, gid_t gid);
-int get_size(const char *uuid, const char *pkgname, int userid,
-        const char *apkpath, const char *libdirpath,
-        const char *fwdlock_apkpath, const char *asecpath,
-        const char *instruction_set, int64_t *codesize, int64_t *datasize,
-        int64_t *cachesize, int64_t *asecsize);
-int free_cache(const char *uuid, int64_t free_size);
-int dexopt(const char *apk_path, uid_t uid, bool is_public, const char *pkgName,
-           const char *instruction_set, int dexopt_needed, bool vm_safe_mode,
-           bool debuggable, const char* oat_dir, bool boot_complete);
-int mark_boot_complete(const char *instruction_set);
-int movefiles();
-int linklib(const char* uuid, const char* pkgname, const char* asecLibDir, int userId);
-int idmap(const char *target_path, const char *overlay_path, uid_t uid);
-int restorecon_data(const char *uuid, const char* pkgName, const char* seinfo, uid_t uid);
-int create_oat_dir(const char* oat_dir, const char *instruction_set);
-int rm_package_dir(const char* apk_path);
-int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
-                            const char *instruction_set);
-int move_package_dir(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
-                            const char *instruction_set);
-int link_file(const char *relative_path, const char *from_base, const char *to_base);
diff --git a/cmds/installd/installd.rc b/cmds/installd/installd.rc
new file mode 100644
index 0000000..5e4c925
--- /dev/null
+++ b/cmds/installd/installd.rc
@@ -0,0 +1,3 @@
+service installd /system/bin/installd
+    class main
+    socket installd stream 600 system system
diff --git a/cmds/installd/installd_constants.h b/cmds/installd/installd_constants.h
new file mode 100644
index 0000000..8513695
--- /dev/null
+++ b/cmds/installd/installd_constants.h
@@ -0,0 +1,99 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** 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.
+*/
+
+#ifndef INSTALLD_CONSTANTS_H_
+#define INSTALLD_CONSTANTS_H_
+
+namespace android {
+namespace installd {
+
+/* elements combined with a valid package name to form paths */
+
+constexpr const char* PRIMARY_USER_PREFIX = "data/";
+constexpr const char* SECONDARY_USER_PREFIX = "user/";
+
+constexpr const char* PKG_DIR_POSTFIX = "";
+
+constexpr const char* PKG_LIB_POSTFIX = "/lib";
+
+constexpr const char* CACHE_DIR_POSTFIX = "/cache";
+constexpr const char* CODE_CACHE_DIR_POSTFIX = "/code_cache";
+
+constexpr const char* APP_SUBDIR = "app/"; // sub-directory under ANDROID_DATA
+constexpr const char* PRIV_APP_SUBDIR = "priv-app/"; // sub-directory under ANDROID_DATA
+constexpr const char* EPHEMERAL_APP_SUBDIR = "app-ephemeral/"; // sub-directory under ANDROID_DATA
+
+constexpr const char* APP_LIB_SUBDIR = "app-lib/"; // sub-directory under ANDROID_DATA
+
+constexpr const char* MEDIA_SUBDIR = "media/"; // sub-directory under ANDROID_DATA
+
+constexpr const char* PROFILES_SUBDIR = "misc/profiles"; // sub-directory under ANDROID_DATA
+
+/* other handy constants */
+
+constexpr const char* PRIVATE_APP_SUBDIR = "app-private/"; // sub-directory under ANDROID_DATA
+
+// This is used as a string literal, can't be constants. TODO: std::string...
+#define DALVIK_CACHE "dalvik-cache"
+constexpr const char* DALVIK_CACHE_POSTFIX = "/classes.dex";
+constexpr const char* DALVIK_CACHE_POSTFIX2 = "@classes.dex";
+
+constexpr const char* IDMAP_PREFIX = "/data/resource-cache/";
+constexpr const char* IDMAP_SUFFIX = "@idmap";
+
+constexpr size_t PKG_NAME_MAX = 128u;   /* largest allowed package name */
+constexpr size_t PKG_PATH_MAX = 256u;   /* max size of any path we use */
+
+// NOTE: keep in sync with StorageManager
+constexpr int FLAG_STORAGE_DE = 1 << 0;
+constexpr int FLAG_STORAGE_CE = 1 << 1;
+
+// NOTE: keep in sync with Installer
+constexpr int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
+constexpr int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
+
+/* dexopt needed flags matching those in dalvik.system.DexFile */
+constexpr int DEXOPT_DEX2OAT_NEEDED       = 1;
+constexpr int DEXOPT_PATCHOAT_NEEDED      = 2;
+constexpr int DEXOPT_SELF_PATCHOAT_NEEDED = 3;
+
+/****************************************************************************
+ * IMPORTANT: These values are passed from Java code. Keep them in sync with
+ * frameworks/base/services/core/java/com/android/server/pm/Installer.java
+ ***************************************************************************/
+constexpr int DEXOPT_PUBLIC         = 1 << 1;
+constexpr int DEXOPT_SAFEMODE       = 1 << 2;
+constexpr int DEXOPT_DEBUGGABLE     = 1 << 3;
+constexpr int DEXOPT_BOOTCOMPLETE   = 1 << 4;
+constexpr int DEXOPT_PROFILE_GUIDED = 1 << 5;
+constexpr int DEXOPT_OTA            = 1 << 6;
+
+/* all known values for dexopt flags */
+constexpr int DEXOPT_MASK =
+    DEXOPT_PUBLIC
+    | DEXOPT_SAFEMODE
+    | DEXOPT_DEBUGGABLE
+    | DEXOPT_BOOTCOMPLETE
+    | DEXOPT_PROFILE_GUIDED
+    | DEXOPT_OTA;
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // INSTALLD_CONSTANTS_H_
diff --git a/cmds/installd/installd_deps.h b/cmds/installd/installd_deps.h
new file mode 100644
index 0000000..5ff46e6
--- /dev/null
+++ b/cmds/installd/installd_deps.h
@@ -0,0 +1,66 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** 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.
+*/
+
+#ifndef INSTALLD_DEPS_H_
+#define INSTALLD_DEPS_H_
+
+#include <inttypes.h>
+
+#include <installd_constants.h>
+
+namespace android {
+namespace installd {
+
+// Dependencies for a full binary. These functions need to be provided to
+// figure out parts of the configuration.
+
+// Retrieve a system property. Same API as cutils, just renamed.
+extern int get_property(const char *key,
+                        char *value,
+                        const char *default_value);
+// Size constants. Should be checked to be equal to the cutils requirements.
+constexpr size_t kPropertyKeyMax = 32u;
+constexpr size_t kPropertyValueMax = 92u;
+
+// Compute the output path for dex2oat.
+extern bool calculate_oat_file_path(char path[PKG_PATH_MAX],
+                                    const char *oat_dir,
+                                    const char *apk_path,
+                                    const char *instruction_set);
+// Compute the output path for patchoat.
+//
+// Computes the odex file for the given apk_path and instruction_set, e.g.,
+// /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
+//
+// Returns false if it failed to determine the odex file path.
+//
+extern bool calculate_odex_file_path(char path[PKG_PATH_MAX],
+                                     const char *apk_path,
+                                     const char *instruction_set);
+
+// Compute the output path into the dalvik cache.
+extern bool create_cache_path(char path[PKG_PATH_MAX],
+                              const char *src,
+                              const char *instruction_set);
+
+// Initialize globals. May be implemented with the helper in globals.h.
+extern bool initialize_globals();
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // INSTALLD_DEPS_H_
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
new file mode 100644
index 0000000..ac511ec
--- /dev/null
+++ b/cmds/installd/otapreopt.cpp
@@ -0,0 +1,687 @@
+/*
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** 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 <algorithm>
+#include <inttypes.h>
+#include <random>
+#include <regex>
+#include <selinux/android.h>
+#include <selinux/avc.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <private/android_filesystem_config.h>
+
+#include <commands.h>
+#include <file_parsing.h>
+#include <globals.h>
+#include <installd_deps.h>  // Need to fill in requirements of commands.
+#include <string_helpers.h>
+#include <system_properties.h>
+#include <utils.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "otapreopt"
+#endif
+
+#define BUFFER_MAX    1024  /* input buffer for commands */
+#define TOKEN_MAX     16    /* max number of arguments in buffer */
+#define REPLY_MAX     256   /* largest reply allowed */
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace installd {
+
+static constexpr const char* kBootClassPathPropertyName = "BOOTCLASSPATH";
+static constexpr const char* kAndroidRootPathPropertyName = "ANDROID_ROOT";
+static constexpr const char* kOTARootDirectory = "/system-b";
+static constexpr size_t kISAIndex = 3;
+
+template<typename T>
+static constexpr T RoundDown(T x, typename std::decay<T>::type n) {
+    return DCHECK_CONSTEXPR(IsPowerOfTwo(n), , T(0))(x & -n);
+}
+
+template<typename T>
+static constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
+    return RoundDown(x + n - 1, n);
+}
+
+class OTAPreoptService {
+ public:
+    static constexpr const char* kOTADataDirectory = "/data/ota";
+
+    // Main driver. Performs the following steps.
+    //
+    // 1) Parse options (read system properties etc from B partition).
+    //
+    // 2) Read in package data.
+    //
+    // 3) Prepare environment variables.
+    //
+    // 4) Prepare(compile) boot image, if necessary.
+    //
+    // 5) Run update.
+    int Main(int argc, char** argv) {
+        if (!ReadSystemProperties()) {
+            LOG(ERROR)<< "Failed reading system properties.";
+            return 1;
+        }
+
+        if (!ReadEnvironment()) {
+            LOG(ERROR) << "Failed reading environment properties.";
+            return 2;
+        }
+
+        if (!ReadPackage(argc, argv)) {
+            LOG(ERROR) << "Failed reading command line file.";
+            return 3;
+        }
+
+        PrepareEnvironment();
+
+        if (!PrepareBootImage()) {
+            LOG(ERROR) << "Failed preparing boot image.";
+            return 4;
+        }
+
+        int dexopt_retcode = RunPreopt();
+
+        return dexopt_retcode;
+    }
+
+    int GetProperty(const char* key, char* value, const char* default_value) {
+        const std::string* prop_value = system_properties_.GetProperty(key);
+        if (prop_value == nullptr) {
+            if (default_value == nullptr) {
+                return 0;
+            }
+            // Copy in the default value.
+            strncpy(value, default_value, kPropertyValueMax - 1);
+            value[kPropertyValueMax - 1] = 0;
+            return strlen(default_value);// TODO: Need to truncate?
+        }
+        size_t size = std::min(kPropertyValueMax - 1, prop_value->length());
+        strncpy(value, prop_value->data(), size);
+        value[size] = 0;
+        return static_cast<int>(size);
+    }
+
+private:
+    bool ReadSystemProperties() {
+        static constexpr const char* kPropertyFiles[] = {
+                "/default.prop", "/system/build.prop"
+        };
+
+        for (size_t i = 0; i < arraysize(kPropertyFiles); ++i) {
+            if (!system_properties_.Load(kPropertyFiles[i])) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    bool ReadEnvironment() {
+        // Parse the environment variables from init.environ.rc, which have the form
+        //   export NAME VALUE
+        // For simplicity, don't respect string quotation. The values we are interested in can be
+        // encoded without them.
+        std::regex export_regex("\\s*export\\s+(\\S+)\\s+(\\S+)");
+        bool parse_result = ParseFile("/init.environ.rc", [&](const std::string& line) {
+            std::smatch export_match;
+            if (!std::regex_match(line, export_match, export_regex)) {
+                return true;
+            }
+
+            if (export_match.size() != 3) {
+                return true;
+            }
+
+            std::string name = export_match[1].str();
+            std::string value = export_match[2].str();
+
+            system_properties_.SetProperty(name, value);
+
+            return true;
+        });
+        if (!parse_result) {
+            return false;
+        }
+
+        // Check that we found important properties.
+        constexpr const char* kRequiredProperties[] = {
+                kBootClassPathPropertyName, kAndroidRootPathPropertyName
+        };
+        for (size_t i = 0; i < arraysize(kRequiredProperties); ++i) {
+            if (system_properties_.GetProperty(kRequiredProperties[i]) == nullptr) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    bool ReadPackage(int argc ATTRIBUTE_UNUSED, char** argv) {
+        size_t index = 0;
+        while (index < ARRAY_SIZE(package_parameters_) &&
+                argv[index + 1] != nullptr) {
+            package_parameters_[index] = argv[index + 1];
+            index++;
+        }
+        if (index != ARRAY_SIZE(package_parameters_)) {
+            LOG(ERROR) << "Wrong number of parameters";
+            return false;
+        }
+
+        return true;
+    }
+
+    void PrepareEnvironment() {
+        CHECK(system_properties_.GetProperty(kBootClassPathPropertyName) != nullptr);
+        const std::string& boot_cp =
+                *system_properties_.GetProperty(kBootClassPathPropertyName);
+        environ_.push_back(StringPrintf("BOOTCLASSPATH=%s", boot_cp.c_str()));
+        environ_.push_back(StringPrintf("ANDROID_DATA=%s", kOTADataDirectory));
+        CHECK(system_properties_.GetProperty(kAndroidRootPathPropertyName) != nullptr);
+        const std::string& android_root =
+                *system_properties_.GetProperty(kAndroidRootPathPropertyName);
+        environ_.push_back(StringPrintf("ANDROID_ROOT=%s", android_root.c_str()));
+
+        for (const std::string& e : environ_) {
+            putenv(const_cast<char*>(e.c_str()));
+        }
+    }
+
+    // Ensure that we have the right boot image. The first time any app is
+    // compiled, we'll try to generate it.
+    bool PrepareBootImage() {
+        if (package_parameters_[kISAIndex] == nullptr) {
+            LOG(ERROR) << "Instruction set missing.";
+            return false;
+        }
+        const char* isa = package_parameters_[kISAIndex];
+
+        // Check whether the file exists where expected.
+        std::string dalvik_cache = std::string(kOTADataDirectory) + "/" + DALVIK_CACHE;
+        std::string isa_path = dalvik_cache + "/" + isa;
+        std::string art_path = isa_path + "/system@framework@boot.art";
+        std::string oat_path = isa_path + "/system@framework@boot.oat";
+        if (access(art_path.c_str(), F_OK) == 0 &&
+                access(oat_path.c_str(), F_OK) == 0) {
+            // Files exist, assume everything is alright.
+            return true;
+        }
+
+        // Create the directories, if necessary.
+        if (access(dalvik_cache.c_str(), F_OK) != 0) {
+            if (mkdir(dalvik_cache.c_str(), 0711) != 0) {
+                PLOG(ERROR) << "Could not create dalvik-cache dir";
+                return false;
+            }
+        }
+        if (access(isa_path.c_str(), F_OK) != 0) {
+            if (mkdir(isa_path.c_str(), 0711) != 0) {
+                PLOG(ERROR) << "Could not create dalvik-cache isa dir";
+                return false;
+            }
+        }
+
+        // Prepare to create.
+        // TODO: Delete files, just for a blank slate.
+        const std::string& boot_cp = *system_properties_.GetProperty(kBootClassPathPropertyName);
+
+        std::string preopted_boot_art_path = StringPrintf("/system/framework/%s/boot.art", isa);
+        if (access(preopted_boot_art_path.c_str(), F_OK) == 0) {
+          return PatchoatBootImage(art_path, isa);
+        } else {
+          // No preopted boot image. Try to compile.
+          return Dex2oatBootImage(boot_cp, art_path, oat_path, isa);
+        }
+    }
+
+    bool PatchoatBootImage(const std::string& art_path, const char* isa) {
+        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
+
+        std::vector<std::string> cmd;
+        cmd.push_back("/system/bin/patchoat");
+
+        cmd.push_back("--input-image-location=/system/framework/boot.art");
+        cmd.push_back(StringPrintf("--output-image-file=%s", art_path.c_str()));
+
+        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
+
+        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
+                                                          ART_BASE_ADDRESS_MAX_DELTA);
+        cmd.push_back(StringPrintf("--base-offset-delta=%d", base_offset));
+
+        std::string error_msg;
+        bool result = Exec(cmd, &error_msg);
+        if (!result) {
+            LOG(ERROR) << "Could not generate boot image: " << error_msg;
+        }
+        return result;
+    }
+
+    bool Dex2oatBootImage(const std::string& boot_cp,
+                          const std::string& art_path,
+                          const std::string& oat_path,
+                          const char* isa) {
+        // This needs to be kept in sync with ART, see art/runtime/gc/space/image_space.cc.
+        std::vector<std::string> cmd;
+        cmd.push_back("/system/bin/dex2oat");
+        cmd.push_back(StringPrintf("--image=%s", art_path.c_str()));
+        for (const std::string& boot_part : Split(boot_cp, ':')) {
+            cmd.push_back(StringPrintf("--dex-file=%s", boot_part.c_str()));
+        }
+        cmd.push_back(StringPrintf("--oat-file=%s", oat_path.c_str()));
+
+        int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA,
+                ART_BASE_ADDRESS_MAX_DELTA);
+        cmd.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset));
+
+        cmd.push_back(StringPrintf("--instruction-set=%s", isa));
+
+        // These things are pushed by AndroidRuntime, see frameworks/base/core/jni/AndroidRuntime.cpp.
+        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xms",
+                "-Xms",
+                true,
+                cmd);
+        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-Xmx",
+                "-Xmx",
+                true,
+                cmd);
+        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-filter",
+                "--compiler-filter=",
+                false,
+                cmd);
+        cmd.push_back("--image-classes=/system/etc/preloaded-classes");
+        // TODO: Compiled-classes.
+        const std::string* extra_opts =
+                system_properties_.GetProperty("dalvik.vm.image-dex2oat-flags");
+        if (extra_opts != nullptr) {
+            std::vector<std::string> extra_vals = Split(*extra_opts, ' ');
+            cmd.insert(cmd.end(), extra_vals.begin(), extra_vals.end());
+        }
+        // TODO: Should we lower this? It's usually set close to max, because
+        //       normally there's not much else going on at boot.
+        AddCompilerOptionFromSystemProperty("dalvik.vm.image-dex2oat-threads",
+                "-j",
+                false,
+                cmd);
+        AddCompilerOptionFromSystemProperty(
+                StringPrintf("dalvik.vm.isa.%s.variant", isa).c_str(),
+                "--instruction-set-variant=",
+                false,
+                cmd);
+        AddCompilerOptionFromSystemProperty(
+                StringPrintf("dalvik.vm.isa.%s.features", isa).c_str(),
+                "--instruction-set-features=",
+                false,
+                cmd);
+
+        std::string error_msg;
+        bool result = Exec(cmd, &error_msg);
+        if (!result) {
+            LOG(ERROR) << "Could not generate boot image: " << error_msg;
+        }
+        return result;
+    }
+
+    static const char* ParseNull(const char* arg) {
+        return (strcmp(arg, "!") == 0) ? nullptr : arg;
+    }
+
+    int RunPreopt() {
+        int ret = dexopt(package_parameters_[0],          // apk_path
+                atoi(package_parameters_[1]),             // uid
+                package_parameters_[2],                   // pkgname
+                package_parameters_[3],                   // instruction_set
+                atoi(package_parameters_[4]),             // dexopt_needed
+                package_parameters_[5],                   // oat_dir
+                atoi(package_parameters_[6]),             // dexopt_flags
+                package_parameters_[7],                   // compiler_filter
+                ParseNull(package_parameters_[8]),        // volume_uuid
+                ParseNull(package_parameters_[9]));       // shared_libraries
+        return ret;
+    }
+
+    ////////////////////////////////////
+    // Helpers, mostly taken from ART //
+    ////////////////////////////////////
+
+    // Wrapper on fork/execv to run a command in a subprocess.
+    bool Exec(const std::vector<std::string>& arg_vector, std::string* error_msg) {
+        const std::string command_line(Join(arg_vector, ' '));
+
+        CHECK_GE(arg_vector.size(), 1U) << command_line;
+
+        // Convert the args to char pointers.
+        const char* program = arg_vector[0].c_str();
+        std::vector<char*> args;
+        for (size_t i = 0; i < arg_vector.size(); ++i) {
+            const std::string& arg = arg_vector[i];
+            char* arg_str = const_cast<char*>(arg.c_str());
+            CHECK(arg_str != nullptr) << i;
+            args.push_back(arg_str);
+        }
+        args.push_back(nullptr);
+
+        // Fork and exec.
+        pid_t pid = fork();
+        if (pid == 0) {
+            // No allocation allowed between fork and exec.
+
+            // Change process groups, so we don't get reaped by ProcessManager.
+            setpgid(0, 0);
+
+            execv(program, &args[0]);
+
+            PLOG(ERROR) << "Failed to execv(" << command_line << ")";
+            // _exit to avoid atexit handlers in child.
+            _exit(1);
+        } else {
+            if (pid == -1) {
+                *error_msg = StringPrintf("Failed to execv(%s) because fork failed: %s",
+                        command_line.c_str(), strerror(errno));
+                return false;
+            }
+
+            // wait for subprocess to finish
+            int status;
+            pid_t got_pid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
+            if (got_pid != pid) {
+                *error_msg = StringPrintf("Failed after fork for execv(%s) because waitpid failed: "
+                        "wanted %d, got %d: %s",
+                        command_line.c_str(), pid, got_pid, strerror(errno));
+                return false;
+            }
+            if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+                *error_msg = StringPrintf("Failed execv(%s) because non-0 exit status",
+                        command_line.c_str());
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Choose a random relocation offset. Taken from art/runtime/gc/image_space.cc.
+    static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) {
+        constexpr size_t kPageSize = PAGE_SIZE;
+        CHECK_EQ(min_delta % kPageSize, 0u);
+        CHECK_EQ(max_delta % kPageSize, 0u);
+        CHECK_LT(min_delta, max_delta);
+
+        std::default_random_engine generator;
+        generator.seed(GetSeed());
+        std::uniform_int_distribution<int32_t> distribution(min_delta, max_delta);
+        int32_t r = distribution(generator);
+        if (r % 2 == 0) {
+            r = RoundUp(r, kPageSize);
+        } else {
+            r = RoundDown(r, kPageSize);
+        }
+        CHECK_LE(min_delta, r);
+        CHECK_GE(max_delta, r);
+        CHECK_EQ(r % kPageSize, 0u);
+        return r;
+    }
+
+    static uint64_t GetSeed() {
+#ifdef __BIONIC__
+        // Bionic exposes arc4random, use it.
+        uint64_t random_data;
+        arc4random_buf(&random_data, sizeof(random_data));
+        return random_data;
+#else
+#error "This is only supposed to run with bionic. Otherwise, implement..."
+#endif
+    }
+
+    void AddCompilerOptionFromSystemProperty(const char* system_property,
+            const char* prefix,
+            bool runtime,
+            std::vector<std::string>& out) {
+        const std::string* value =
+        system_properties_.GetProperty(system_property);
+        if (value != nullptr) {
+            if (runtime) {
+                out.push_back("--runtime-arg");
+            }
+            if (prefix != nullptr) {
+                out.push_back(StringPrintf("%s%s", prefix, value->c_str()));
+            } else {
+                out.push_back(*value);
+            }
+        }
+    }
+
+    // Stores the system properties read out of the B partition. We need to use these properties
+    // to compile, instead of the A properties we could get from init/get_property.
+    SystemProperties system_properties_;
+
+    const char* package_parameters_[10];
+
+    // Store environment values we need to set.
+    std::vector<std::string> environ_;
+};
+
+OTAPreoptService gOps;
+
+////////////////////////
+// Plug-in functions. //
+////////////////////////
+
+int get_property(const char *key, char *value, const char *default_value) {
+    // TODO: Replace with system-properties map.
+    return gOps.GetProperty(key, value, default_value);
+}
+
+// Compute the output path of
+bool calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir,
+                             const char *apk_path,
+                             const char *instruction_set) {
+    // TODO: Insert B directory.
+    char *file_name_start;
+    char *file_name_end;
+
+    file_name_start = strrchr(apk_path, '/');
+    if (file_name_start == nullptr) {
+        ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
+        return false;
+    }
+    file_name_end = strrchr(file_name_start, '.');
+    if (file_name_end == nullptr) {
+        ALOGE("apk_path '%s' has no extension\n", apk_path);
+        return false;
+    }
+
+    // Calculate file_name
+    file_name_start++;  // Move past '/', is valid as file_name_end is valid.
+    size_t file_name_len = file_name_end - file_name_start;
+    std::string file_name(file_name_start, file_name_len);
+
+    // <apk_parent_dir>/oat/<isa>/<file_name>.odex.b
+    snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex.b", oat_dir, instruction_set,
+             file_name.c_str());
+    return true;
+}
+
+/*
+ * Computes the odex file for the given apk_path and instruction_set.
+ * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
+ *
+ * Returns false if it failed to determine the odex file path.
+ */
+bool calculate_odex_file_path(char path[PKG_PATH_MAX], const char *apk_path,
+                              const char *instruction_set) {
+    if (StringPrintf("%soat/%s/odex.b", apk_path, instruction_set).length() + 1 > PKG_PATH_MAX) {
+        ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
+        return false;
+    }
+
+    const char *path_end = strrchr(apk_path, '/');
+    if (path_end == nullptr) {
+        ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
+        return false;
+    }
+    std::string path_component(apk_path, path_end - apk_path);
+
+    const char *name_begin = path_end + 1;
+    const char *extension_start = strrchr(name_begin, '.');
+    if (extension_start == nullptr) {
+        ALOGE("apk_path '%s' has no extension.\n", apk_path);
+        return false;
+    }
+    std::string name_component(name_begin, extension_start - name_begin);
+
+    std::string new_path = StringPrintf("%s/oat/%s/%s.odex.b",
+                                        path_component.c_str(),
+                                        instruction_set,
+                                        name_component.c_str());
+    CHECK_LT(new_path.length(), PKG_PATH_MAX);
+    strcpy(path, new_path.c_str());
+    return true;
+}
+
+bool create_cache_path(char path[PKG_PATH_MAX],
+                       const char *src,
+                       const char *instruction_set) {
+    size_t srclen = strlen(src);
+
+        /* demand that we are an absolute path */
+    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
+        return false;
+    }
+
+    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
+        return false;
+    }
+
+    std::string from_src = std::string(src + 1);
+    std::replace(from_src.begin(), from_src.end(), '/', '@');
+
+    std::string assembled_path = StringPrintf("%s/%s/%s/%s%s",
+                                              OTAPreoptService::kOTADataDirectory,
+                                              DALVIK_CACHE,
+                                              instruction_set,
+                                              from_src.c_str(),
+                                              DALVIK_CACHE_POSTFIX2);
+
+    if (assembled_path.length() + 1 > PKG_PATH_MAX) {
+        return false;
+    }
+    strcpy(path, assembled_path.c_str());
+
+    return true;
+}
+
+bool initialize_globals() {
+    const char* data_path = getenv("ANDROID_DATA");
+    if (data_path == nullptr) {
+        ALOGE("Could not find ANDROID_DATA");
+        return false;
+    }
+    return init_globals_from_data_and_root(data_path, kOTARootDirectory);
+}
+
+static bool initialize_directories() {
+    // This is different from the normal installd. We only do the base
+    // directory, the rest will be created on demand when each app is compiled.
+    mode_t old_umask = umask(0);
+    LOG(INFO) << "Old umask: " << old_umask;
+    if (access(OTAPreoptService::kOTADataDirectory, R_OK) < 0) {
+        ALOGE("Could not access %s\n", OTAPreoptService::kOTADataDirectory);
+        return false;
+    }
+    return true;
+}
+
+static int log_callback(int type, const char *fmt, ...) {
+    va_list ap;
+    int priority;
+
+    switch (type) {
+        case SELINUX_WARNING:
+            priority = ANDROID_LOG_WARN;
+            break;
+        case SELINUX_INFO:
+            priority = ANDROID_LOG_INFO;
+            break;
+        default:
+            priority = ANDROID_LOG_ERROR;
+            break;
+    }
+    va_start(ap, fmt);
+    LOG_PRI_VA(priority, "SELinux", fmt, ap);
+    va_end(ap);
+    return 0;
+}
+
+static int otapreopt_main(const int argc, char *argv[]) {
+    int selinux_enabled = (is_selinux_enabled() > 0);
+
+    setenv("ANDROID_LOG_TAGS", "*:v", 1);
+    android::base::InitLogging(argv);
+
+    ALOGI("otapreopt firing up\n");
+
+    if (argc < 2) {
+        ALOGE("Expecting parameters");
+        exit(1);
+    }
+
+    union selinux_callback cb;
+    cb.func_log = log_callback;
+    selinux_set_callback(SELINUX_CB_LOG, cb);
+
+    if (!initialize_globals()) {
+        ALOGE("Could not initialize globals; exiting.\n");
+        exit(1);
+    }
+
+    if (!initialize_directories()) {
+        ALOGE("Could not create directories; exiting.\n");
+        exit(1);
+    }
+
+    if (selinux_enabled && selinux_status_open(true) < 0) {
+        ALOGE("Could not open selinux status; exiting.\n");
+        exit(1);
+    }
+
+    int ret = android::installd::gOps.Main(argc, argv);
+
+    return ret;
+}
+
+}  // namespace installd
+}  // namespace android
+
+int main(const int argc, char *argv[]) {
+    return android::installd::otapreopt_main(argc, argv);
+}
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
new file mode 100644
index 0000000..f7f69a9
--- /dev/null
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -0,0 +1,99 @@
+/*
+ ** Copyright 2016, The Android Open Source Project
+ **
+ ** 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 <linux/unistd.h>
+#include <sys/mount.h>
+#include <sys/wait.h>
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <android-base/stringprintf.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "otapreopt"
+#endif
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace installd {
+
+static int otapreopt_chroot(const int argc, char **arg) {
+    // We need to run the otapreopt tool from the postinstall partition. As such, set up a
+    // mount namespace and change root.
+
+    // Create our own mount namespace.
+    if (unshare(CLONE_NEWNS) != 0) {
+        PLOG(ERROR) << "Failed to unshare() for otapreopt.";
+        exit(200);
+    }
+
+    // Make postinstall private, so that our changes don't propagate.
+    if (mount("", "/postinstall", nullptr, MS_PRIVATE, nullptr) != 0) {
+        PLOG(ERROR) << "Failed to mount private.";
+        exit(201);
+    }
+
+    // Bind mount necessary directories.
+    constexpr const char* kBindMounts[] = {
+            "/data", "/dev", "/proc", "/sys"
+    };
+    for (size_t i = 0; i < arraysize(kBindMounts); ++i) {
+        std::string trg = StringPrintf("/postinstall%s", kBindMounts[i]);
+        if (mount(kBindMounts[i], trg.c_str(), nullptr, MS_BIND, nullptr) != 0) {
+            PLOG(ERROR) << "Failed to bind-mount " << kBindMounts[i];
+            exit(202);
+        }
+    }
+
+    // Chdir into /postinstall.
+    if (chdir("/postinstall") != 0) {
+        PLOG(ERROR) << "Unable to chdir into /postinstall.";
+        exit(203);
+    }
+
+    // Make /postinstall the root in our mount namespace.
+    if (chroot(".")  != 0) {
+        PLOG(ERROR) << "Failed to chroot";
+        exit(204);
+    }
+
+    if (chdir("/") != 0) {
+        PLOG(ERROR) << "Unable to chdir into /.";
+        exit(205);
+    }
+
+    // Now go on and run otapreopt.
+
+    const char* argv[1 + 9 + 1];
+    CHECK_EQ(argc, 10);
+    argv[0] = "/system/bin/otapreopt";
+    for (size_t i = 1; i <= 9; ++i) {
+        argv[i] = arg[i];
+    }
+    argv[10] = nullptr;
+
+    execv(argv[0], (char * const *)argv);
+    PLOG(ERROR) << "execv(OTAPREOPT) failed.";
+    exit(99);
+}
+
+}  // namespace installd
+}  // namespace android
+
+int main(const int argc, char *argv[]) {
+    return android::installd::otapreopt_chroot(argc, argv);
+}
diff --git a/cmds/installd/otapreopt_script.sh b/cmds/installd/otapreopt_script.sh
new file mode 100644
index 0000000..a31734a
--- /dev/null
+++ b/cmds/installd/otapreopt_script.sh
@@ -0,0 +1,50 @@
+#!/system/bin/sh
+
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# 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.
+#
+
+# This script will run as a postinstall step to drive otapreopt.
+
+# Maximum number of packages/steps.
+MAXIMUM_PACKAGES=1000
+
+PREPARE=$(cmd otadexopt prepare)
+if [ "$PREPARE" != "Success" ] ; then
+  echo "Failed to prepare."
+  exit 1
+fi
+
+i=0
+while ((i<MAXIMUM_PACKAGES)) ; do
+  cmd otadexopt step
+  DONE=$(cmd otadexopt done)
+  if [ "$DONE" = "OTA complete." ] ; then
+    break
+  fi
+  sleep 1
+  i=$((i+1))
+done
+
+DONE=$(cmd otadexopt done)
+if [ "$DONE" = "OTA incomplete." ] ; then
+  echo "Incomplete."
+else
+  echo "Complete or error."
+fi
+
+cmd otadexopt cleanup
+
+exit 0
diff --git a/cmds/installd/string_helpers.h b/cmds/installd/string_helpers.h
new file mode 100644
index 0000000..e8fcdef
--- /dev/null
+++ b/cmds/installd/string_helpers.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ART_OTAPREOPT_STRING_HELPERS_H_
+#define ART_OTAPREOPT_STRING_HELPERS_H_
+
+#include <sstream>
+#include <string>
+
+#include <android-base/macros.h>
+
+namespace android {
+namespace installd {
+
+static inline bool StringStartsWith(const std::string& target,
+                                    const char* prefix) {
+    return target.compare(0, strlen(prefix), prefix) == 0;
+}
+
+// Split the input according to the separator character. Doesn't honor quotation.
+static inline std::vector<std::string> Split(const std::string& in, const char separator) {
+    if (in.empty()) {
+        return std::vector<std::string>();
+    }
+
+    std::vector<std::string> ret;
+    std::stringstream strstr(in);
+    std::string token;
+
+    while (std::getline(strstr, token, separator)) {
+        ret.push_back(token);
+    }
+
+    return ret;
+}
+
+template <typename StringT>
+static inline std::string Join(const std::vector<StringT>& strings, char separator) {
+    if (strings.empty()) {
+        return "";
+    }
+
+    std::string result(strings[0]);
+    for (size_t i = 1; i < strings.size(); ++i) {
+        result += separator;
+        result += strings[i];
+    }
+    return result;
+}
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // ART_OTAPREOPT_STRING_HELPERS_H_
diff --git a/cmds/installd/system_properties.h b/cmds/installd/system_properties.h
new file mode 100644
index 0000000..2d940a3
--- /dev/null
+++ b/cmds/installd/system_properties.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef OTAPREOPT_SYSTEM_PROPERTIES_H_
+#define OTAPREOPT_SYSTEM_PROPERTIES_H_
+
+#include <fstream>
+#include <string>
+#include <unordered_map>
+
+#include <file_parsing.h>
+
+namespace android {
+namespace installd {
+
+// Helper class to read system properties into and manage as a string->string map.
+class SystemProperties {
+ public:
+    bool Load(const std::string& strFile) {
+        return ParseFile(strFile, [&](const std::string& line) {
+            size_t equals_pos = line.find('=');
+            if (equals_pos == std::string::npos || equals_pos == 0) {
+                // Did not find equals sign, or it's the first character - isn't a valid line.
+                return true;
+            }
+
+            std::string key = line.substr(0, equals_pos);
+            std::string value = line.substr(equals_pos + 1,
+                                            line.length() - equals_pos + 1);
+
+            properties_.insert(std::make_pair(key, value));
+
+            return true;
+        });
+    }
+
+    // Look up the key in the map. Returns null if the key isn't mapped.
+    const std::string* GetProperty(const std::string& key) const {
+        auto it = properties_.find(key);
+        if (it != properties_.end()) {
+            return &it->second;
+        }
+        return nullptr;
+    }
+
+    void SetProperty(const std::string& key, const std::string& value) {
+        properties_.insert(std::make_pair(key, value));
+    }
+
+ private:
+    // The actual map.
+    std::unordered_map<std::string, std::string> properties_;
+};
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // OTAPREOPT_SYSTEM_PROPERTIES_H_
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index 5e397f9..9b2de88 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -19,7 +19,9 @@
 
 #include <gtest/gtest.h>
 
-#include "installd.h"
+#include <commands.h>
+#include <globals.h>
+#include <utils.h>
 
 #undef LOG_TAG
 #define LOG_TAG "utils_test"
@@ -44,6 +46,7 @@
         "shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_shared_prefs_"
 
 namespace android {
+namespace installd {
 
 class UtilsTest : public testing::Test {
 protected:
@@ -319,8 +322,8 @@
     EXPECT_EQ(0, create_pkg_path(path, pkgname, "", 0))
             << "Should successfully be able to create package name.";
 
-    const char *prefix = TEST_DATA_DIR PRIMARY_USER_PREFIX;
-    size_t offset = strlen(prefix);
+    std::string prefix = std::string(TEST_DATA_DIR) + PRIMARY_USER_PREFIX;
+    size_t offset = prefix.length();
 
     EXPECT_STREQ(pkgname, path + offset)
              << "Package path should be a really long string of a's";
@@ -358,7 +361,10 @@
     EXPECT_EQ(0, create_pkg_path(path, "com.example.package", "", 0))
             << "Should return error because postfix is too long.";
 
-    EXPECT_STREQ(TEST_DATA_DIR PRIMARY_USER_PREFIX "com.example.package", path)
+    std::string p = std::string(TEST_DATA_DIR)
+                    + PRIMARY_USER_PREFIX
+                    + "com.example.package";
+    EXPECT_STREQ(p.c_str(), path)
             << "Package path should be in /data/data/";
 }
 
@@ -368,7 +374,10 @@
     EXPECT_EQ(0, create_pkg_path(path, "com.example.package", "", 1))
             << "Should successfully create package path.";
 
-    EXPECT_STREQ(TEST_DATA_DIR SECONDARY_USER_PREFIX "1/com.example.package", path)
+    std::string p = std::string(TEST_DATA_DIR)
+                    + SECONDARY_USER_PREFIX
+                    + "1/com.example.package";
+    EXPECT_STREQ(p.c_str(), path)
             << "Package path should be in /data/user/";
 }
 
@@ -463,13 +472,13 @@
 }
 
 TEST_F(UtilsTest, CreateDataUserPath) {
-    EXPECT_EQ("/data/data", create_data_user_path(nullptr, 0));
-    EXPECT_EQ("/data/user/10", create_data_user_path(nullptr, 10));
+    EXPECT_EQ("/data/data", create_data_user_ce_path(nullptr, 0));
+    EXPECT_EQ("/data/user/10", create_data_user_ce_path(nullptr, 10));
 
     EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0",
-            create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
+            create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0));
     EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10",
-            create_data_user_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
+            create_data_user_ce_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
 }
 
 TEST_F(UtilsTest, CreateDataMediaPath) {
@@ -490,13 +499,14 @@
 }
 
 TEST_F(UtilsTest, CreateDataUserPackagePath) {
-    EXPECT_EQ("/data/data/com.example", create_data_user_package_path(nullptr, 0, "com.example"));
-    EXPECT_EQ("/data/user/10/com.example", create_data_user_package_path(nullptr, 10, "com.example"));
+    EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example"));
+    EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example"));
 
     EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/0/com.example",
-            create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
+            create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 0, "com.example"));
     EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/user/10/com.example",
-            create_data_user_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
+            create_data_user_ce_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10, "com.example"));
 }
 
-}
+}  // namespace installd
+}  // namespace android
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 7db3fb9..90d2a9e 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -14,15 +14,38 @@
 ** limitations under the License.
 */
 
-#include "installd.h"
+#include "utils.h"
 
-#include <base/stringprintf.h>
-#include <base/logging.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
 
+#if defined(__APPLE__)
+#include <sys/mount.h>
+#else
+#include <sys/statfs.h>
+#endif
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+#include "globals.h"  // extern variables.
+
+#ifndef LOG_TAG
+#define LOG_TAG "installd"
+#endif
 #define CACHE_NOISY(x) //x
 
 using android::base::StringPrintf;
 
+namespace android {
+namespace installd {
+
 /**
  * Check that given string is valid filename, and that it attempts no
  * parent or child directory traversal.
@@ -36,6 +59,11 @@
     }
 }
 
+static void check_package_name(const char* package_name) {
+    CHECK(is_valid_filename(package_name));
+    CHECK(is_valid_package_name(package_name) == 0);
+}
+
 /**
  * Create the path name where package app contents should be stored for
  * the given volume UUID and package name.  An empty UUID is assumed to
@@ -43,9 +71,7 @@
  */
 std::string create_data_app_package_path(const char* volume_uuid,
         const char* package_name) {
-    CHECK(is_valid_filename(package_name));
-    CHECK(is_valid_package_name(package_name) == 0);
-
+    check_package_name(package_name);
     return StringPrintf("%s/%s",
             create_data_app_path(volume_uuid).c_str(), package_name);
 }
@@ -55,13 +81,51 @@
  * volume UUID, package name, and user ID. An empty UUID is assumed to be
  * internal storage.
  */
-std::string create_data_user_package_path(const char* volume_uuid,
+std::string create_data_user_ce_package_path(const char* volume_uuid,
         userid_t user, const char* package_name) {
-    CHECK(is_valid_filename(package_name));
-    CHECK(is_valid_package_name(package_name) == 0);
-
+    check_package_name(package_name);
     return StringPrintf("%s/%s",
-            create_data_user_path(volume_uuid, user).c_str(), package_name);
+            create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
+}
+
+std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
+        const char* package_name, ino_t ce_data_inode) {
+    // For testing purposes, rely on the inode when defined; this could be
+    // optimized to use access() in the future.
+    auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
+    if (ce_data_inode != 0) {
+        auto user_path = create_data_user_ce_path(volume_uuid, user);
+        DIR* dir = opendir(user_path.c_str());
+        if (dir == nullptr) {
+            PLOG(ERROR) << "Failed to opendir " << user_path;
+            return fallback;
+        }
+
+        struct dirent* ent;
+        while ((ent = readdir(dir))) {
+            if (ent->d_ino == ce_data_inode) {
+                auto resolved = StringPrintf("%s/%s", user_path.c_str(), ent->d_name);
+                if (resolved != fallback) {
+                    LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
+                            << " instead of " << fallback;
+                }
+                closedir(dir);
+                return resolved;
+            }
+        }
+        LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
+        closedir(dir);
+        return fallback;
+    } else {
+        return fallback;
+    }
+}
+
+std::string create_data_user_de_package_path(const char* volume_uuid,
+        userid_t user, const char* package_name) {
+    check_package_name(package_name);
+    return StringPrintf("%s/%s",
+            create_data_user_de_path(volume_uuid, user).c_str(), package_name);
 }
 
 int create_pkg_path(char path[PKG_PATH_MAX], const char *pkgname,
@@ -71,7 +135,7 @@
         return -1;
     }
 
-    std::string _tmp(create_data_user_package_path(nullptr, userid, pkgname) + postfix);
+    std::string _tmp(create_data_user_ce_package_path(nullptr, userid, pkgname) + postfix);
     const char* tmp = _tmp.c_str();
     if (strlen(tmp) >= PKG_PATH_MAX) {
         path[0] = '\0';
@@ -101,7 +165,7 @@
 /**
  * Create the path name for user data for a certain userid.
  */
-std::string create_data_user_path(const char* volume_uuid, userid_t userid) {
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
     std::string data(create_data_path(volume_uuid));
     if (volume_uuid == nullptr) {
         if (userid == 0) {
@@ -115,12 +179,38 @@
 }
 
 /**
+ * Create the path name for device encrypted user data for a certain userid.
+ */
+std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) {
+    std::string data(create_data_path(volume_uuid));
+    return StringPrintf("%s/user_de/%u", data.c_str(), userid);
+}
+
+/**
  * Create the path name for media for a certain userid.
  */
 std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
 }
 
+std::string create_data_misc_legacy_path(userid_t userid) {
+    return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
+}
+
+std::string create_data_user_profiles_path(userid_t userid) {
+    return StringPrintf("%s/cur/%u", android_profiles_dir.path, userid);
+}
+
+std::string create_data_user_profile_package_path(userid_t user, const char* package_name) {
+    check_package_name(package_name);
+    return StringPrintf("%s/%s",create_data_user_profiles_path(user).c_str(), package_name);
+}
+
+std::string create_data_ref_profile_package_path(const char* package_name) {
+    check_package_name(package_name);
+    return StringPrintf("%s/ref/%s", android_profiles_dir.path, package_name);
+}
+
 std::vector<userid_t> get_known_users(const char* volume_uuid) {
     std::vector<userid_t> users;
 
@@ -153,21 +243,10 @@
     return users;
 }
 
-/**
- * Create the path name for config for a certain userid.
- * Returns 0 on success, and -1 on failure.
- */
-int create_user_config_path(char path[PATH_MAX], userid_t userid) {
-    if (snprintf(path, PATH_MAX, "%s%d", "/data/misc/user/", userid) > PATH_MAX) {
-        return -1;
-    }
-    return 0;
-}
-
 int create_move_path(char path[PKG_PATH_MAX],
     const char* pkgname,
     const char* leaf,
-    userid_t userid __unused)
+    userid_t userid ATTRIBUTE_UNUSED)
 {
     if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
             >= PKG_PATH_MAX) {
@@ -256,7 +335,7 @@
                 if ((name[1] == '.') && (name[2] == 0)) continue;
             }
 
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
             if (subfd < 0) {
                 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
                 result = -1;
@@ -288,15 +367,27 @@
     return result;
 }
 
+int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
+    return delete_dir_contents(pathname.c_str(), 0, NULL, ignore_if_missing);
+}
+
+int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) {
+    return delete_dir_contents(pathname.c_str(), 1, NULL, ignore_if_missing);
+}
+
 int delete_dir_contents(const char *pathname,
                         int also_delete_dir,
-                        int (*exclusion_predicate)(const char*, const int))
+                        int (*exclusion_predicate)(const char*, const int),
+                        bool ignore_if_missing)
 {
     int res = 0;
     DIR *d;
 
     d = opendir(pathname);
     if (d == NULL) {
+        if (ignore_if_missing && (errno == ENOENT)) {
+            return 0;
+        }
         ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
         return -errno;
     }
@@ -316,7 +407,7 @@
     int fd, res;
     DIR *d;
 
-    fd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+    fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
     if (fd < 0) {
         ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
         return -1;
@@ -656,7 +747,7 @@
                 if ((name[1] == '.') && (name[2] == 0)) continue;
             }
 
-            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
+            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
             if (subfd < 0) {
                 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
                 continue;
@@ -1054,6 +1145,8 @@
         dir = &android_app_dir;
     } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
         dir = &android_app_private_dir;
+    } else if (!strncmp(path, android_app_ephemeral_dir.path, android_app_ephemeral_dir.len)) {
+        dir = &android_app_ephemeral_dir;
     } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
         dir = &android_asec_dir;
     } else if (!strncmp(path, android_mnt_expand_dir.path, android_mnt_expand_dir.len)) {
@@ -1118,67 +1211,41 @@
     return result;
 }
 
-/* Ensure that /data/media directories are prepared for given user. */
-int ensure_media_user_dirs(const char* uuid, userid_t userid) {
-    std::string media_user_path(create_data_media_path(uuid, userid));
-    if (fs_prepare_dir(media_user_path.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
-        return -1;
-    }
-
-    return 0;
-}
-
 int ensure_config_user_dirs(userid_t userid) {
-    char config_user_path[PATH_MAX];
-
     // writable by system, readable by any app within the same user
     const int uid = multiuser_get_uid(userid, AID_SYSTEM);
     const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
 
     // Ensure /data/misc/user/<userid> exists
-    create_user_config_path(config_user_path, userid);
-    if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) {
-        return -1;
+    auto path = create_data_misc_legacy_path(userid);
+    return fs_prepare_dir(path.c_str(), 0750, uid, gid);
+}
+
+int wait_child(pid_t pid)
+{
+    int status;
+    pid_t got_pid;
+
+    while (1) {
+        got_pid = waitpid(pid, &status, 0);
+        if (got_pid == -1 && errno == EINTR) {
+            printf("waitpid interrupted, retrying\n");
+        } else {
+            break;
+        }
+    }
+    if (got_pid != pid) {
+        ALOGW("waitpid failed: wanted %d, got %d: %s\n",
+            (int) pid, (int) got_pid, strerror(errno));
+        return 1;
     }
 
-   return 0;
-}
-
-int create_profile_file(const char *pkgname, gid_t gid) {
-    const char *profile_dir = DALVIK_CACHE_PREFIX "profiles";
-    char profile_file[PKG_PATH_MAX];
-
-    snprintf(profile_file, sizeof(profile_file), "%s/%s", profile_dir, pkgname);
-
-    // The 'system' user needs to be able to read the profile to determine if dex2oat
-    // needs to be run.  This is done in dalvik.system.DexFile.isDexOptNeededInternal().  So
-    // we assign ownership to AID_SYSTEM and ensure it's not world-readable.
-
-    int fd = open(profile_file, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0660);
-
-    // Always set the uid/gid/permissions. The file could have been previously created
-    // with different permissions.
-    if (fd >= 0) {
-        if (fchown(fd, AID_SYSTEM, gid) < 0) {
-            ALOGE("cannot chown profile file '%s': %s\n", profile_file, strerror(errno));
-            close(fd);
-            unlink(profile_file);
-            return -1;
-        }
-
-        if (fchmod(fd, 0660) < 0) {
-            ALOGE("cannot chmod profile file '%s': %s\n", profile_file, strerror(errno));
-            close(fd);
-            unlink(profile_file);
-            return -1;
-        }
-        close(fd);
+    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+        return 0;
+    } else {
+        return status;      /* always nonzero */
     }
-    return 0;
 }
 
-void remove_profile_file(const char *pkgname) {
-    char profile_file[PKG_PATH_MAX];
-    snprintf(profile_file, sizeof(profile_file), "%s/%s", DALVIK_CACHE_PREFIX "profiles", pkgname);
-    unlink(profile_file);
-}
+}  // namespace installd
+}  // namespace android
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
new file mode 100644
index 0000000..477baea
--- /dev/null
+++ b/cmds/installd/utils.h
@@ -0,0 +1,152 @@
+/*
+**
+** Copyright 2008, The Android Open Source Project
+**
+** 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.
+*/
+
+#ifndef UTILS_H_
+#define UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include <dirent.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <utime.h>
+
+#include <cutils/multiuser.h>
+
+#include <installd_constants.h>
+
+namespace android {
+namespace installd {
+
+struct dir_rec_t;
+
+typedef struct cache_dir_struct {
+    struct cache_dir_struct* parent;
+    int32_t childCount;
+    int32_t hiddenCount;
+    int32_t deleted;
+    char name[];
+} cache_dir_t;
+
+typedef struct {
+    cache_dir_t* dir;
+    time_t modTime;
+    char name[];
+} cache_file_t;
+
+typedef struct {
+    size_t numDirs;
+    size_t availDirs;
+    cache_dir_t** dirs;
+    size_t numFiles;
+    size_t availFiles;
+    cache_file_t** files;
+    size_t numCollected;
+    void* memBlocks;
+    int8_t* curMemBlockAvail;
+    int8_t* curMemBlockEnd;
+} cache_t;
+
+int create_pkg_path(char path[PKG_PATH_MAX],
+                    const char *pkgname,
+                    const char *postfix,
+                    userid_t userid);
+
+std::string create_data_path(const char* volume_uuid);
+
+std::string create_data_app_path(const char* volume_uuid);
+
+std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
+
+std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid);
+std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
+
+std::string create_data_user_ce_package_path(const char* volume_uuid,
+        userid_t user, const char* package_name);
+std::string create_data_user_ce_package_path(const char* volume_uuid,
+        userid_t user, const char* package_name, ino_t ce_data_inode);
+std::string create_data_user_de_package_path(const char* volume_uuid,
+        userid_t user, const char* package_name);
+
+std::string create_data_media_path(const char* volume_uuid, userid_t userid);
+
+std::string create_data_misc_legacy_path(userid_t userid);
+
+std::string create_data_user_profiles_path(userid_t userid);
+std::string create_data_user_profile_package_path(userid_t user, const char* package_name);
+std::string create_data_ref_profile_package_path(const char* package_name);
+
+std::vector<userid_t> get_known_users(const char* volume_uuid);
+
+int create_user_config_path(char path[PKG_PATH_MAX], userid_t userid);
+
+int create_move_path(char path[PKG_PATH_MAX],
+                     const char* pkgname,
+                     const char* leaf,
+                     userid_t userid);
+
+int is_valid_package_name(const char* pkgname);
+
+int delete_dir_contents(const std::string& pathname, bool ignore_if_missing = false);
+int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing = false);
+
+int delete_dir_contents(const char *pathname,
+                        int also_delete_dir,
+                        int (*exclusion_predicate)(const char *name, const int is_dir),
+                        bool ignore_if_missing = false);
+
+int delete_dir_contents_fd(int dfd, const char *name);
+
+int copy_dir_files(const char *srcname, const char *dstname, uid_t owner, gid_t group);
+
+int lookup_media_dir(char basepath[PATH_MAX], const char *dir);
+
+int64_t data_disk_free(const std::string& data_path);
+
+cache_t* start_cache_collection();
+
+void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir);
+
+void clear_cache_files(const std::string& data_path, cache_t* cache, int64_t free_size);
+
+void finish_cache_collection(cache_t* cache);
+
+int validate_system_app_path(const char* path);
+
+int get_path_from_env(dir_rec_t* rec, const char* var);
+
+int get_path_from_string(dir_rec_t* rec, const char* path);
+
+int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix);
+
+int validate_apk_path(const char *path);
+int validate_apk_path_subdirs(const char *path);
+
+int append_and_increment(char** dst, const char* src, size_t* dst_size);
+
+char *build_string2(const char *s1, const char *s2);
+char *build_string3(const char *s1, const char *s2, const char *s3);
+
+int ensure_config_user_dirs(userid_t userid);
+
+int wait_child(pid_t pid);
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // UTILS_H_
diff --git a/cmds/servicemanager/Android.mk b/cmds/servicemanager/Android.mk
index 155cfc5..73c0367 100644
--- a/cmds/servicemanager/Android.mk
+++ b/cmds/servicemanager/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 
 svc_c_flags =	\
-	-Wall -Wextra \
+	-Wall -Wextra -Werror \
 
 ifneq ($(TARGET_USES_64_BIT_BINDER),true)
 ifneq ($(TARGET_IS_64_BIT),true)
@@ -22,4 +22,5 @@
 LOCAL_SRC_FILES := service_manager.c binder.c
 LOCAL_CFLAGS += $(svc_c_flags)
 LOCAL_MODULE := servicemanager
+LOCAL_INIT_RC := servicemanager.rc
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/servicemanager/bctest.c b/cmds/servicemanager/bctest.c
index fd91633..6466654 100644
--- a/cmds/servicemanager/bctest.c
+++ b/cmds/servicemanager/bctest.c
@@ -58,7 +58,6 @@
 
 int main(int argc, char **argv)
 {
-    int fd;
     struct binder_state *bs;
     uint32_t svcmgr = BINDER_SERVICE_MANAGER;
     uint32_t handle;
diff --git a/cmds/servicemanager/binder.c b/cmds/servicemanager/binder.c
index 6eecee1..01218c9 100644
--- a/cmds/servicemanager/binder.c
+++ b/cmds/servicemanager/binder.c
@@ -104,7 +104,7 @@
         return NULL;
     }
 
-    bs->fd = open("/dev/binder", O_RDWR);
+    bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
     if (bs->fd < 0) {
         fprintf(stderr,"binder: cannot open device (%s)\n",
                 strerror(errno));
@@ -167,20 +167,27 @@
     return res;
 }
 
-void binder_send_reply(struct binder_state *bs,
-                       struct binder_io *reply,
-                       binder_uintptr_t buffer_to_free,
-                       int status)
+void binder_free_buffer(struct binder_state *bs,
+                        binder_uintptr_t buffer_to_free)
 {
     struct {
         uint32_t cmd_free;
         binder_uintptr_t buffer;
+    } __attribute__((packed)) data;
+    data.cmd_free = BC_FREE_BUFFER;
+    data.buffer = buffer_to_free;
+    binder_write(bs, &data, sizeof(data));
+}
+
+void binder_send_reply(struct binder_state *bs,
+                       struct binder_io *reply,
+                       int status)
+{
+    struct {
         uint32_t cmd_reply;
         struct binder_transaction_data txn;
     } __attribute__((packed)) data;
 
-    data.cmd_free = BC_FREE_BUFFER;
-    data.buffer = buffer_to_free;
     data.cmd_reply = BC_REPLY;
     data.txn.target.ptr = 0;
     data.txn.cookie = 0;
@@ -243,7 +250,9 @@
                 bio_init(&reply, rdata, sizeof(rdata), 4);
                 bio_init_from_txn(&msg, txn);
                 res = func(bs, txn, &msg, &reply);
-                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
+                binder_free_buffer(bs, txn->data.ptr.buffer);
+                if ((txn->flags & TF_ONE_WAY) == 0)
+                    binder_send_reply(bs, &reply, res);
             }
             ptr += sizeof(*txn);
             break;
@@ -449,7 +458,7 @@
 }
 
 void binder_done(struct binder_state *bs,
-                 struct binder_io *msg,
+                 __unused struct binder_io *msg,
                  struct binder_io *reply)
 {
     struct {
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index 7fa9a39..21fdff0 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -23,6 +23,12 @@
 #include <cutils/log.h>
 #endif
 
+struct audit_data {
+    pid_t pid;
+    uid_t uid;
+    const char *name;
+};
+
 const char *str8(const uint16_t *x, size_t x_len)
 {
     static char buf[128];
@@ -56,34 +62,39 @@
 static char *service_manager_context;
 static struct selabel_handle* sehandle;
 
-static bool check_mac_perms(pid_t spid, const char *tctx, const char *perm, const char *name)
+static bool check_mac_perms(pid_t spid, uid_t uid, const char *tctx, const char *perm, const char *name)
 {
     char *sctx = NULL;
     const char *class = "service_manager";
     bool allowed;
+    struct audit_data ad;
 
     if (getpidcon(spid, &sctx) < 0) {
         ALOGE("SELinux: getpidcon(pid=%d) failed to retrieve pid context.\n", spid);
         return false;
     }
 
-    int result = selinux_check_access(sctx, tctx, class, perm, (void *) name);
+    ad.pid = spid;
+    ad.uid = uid;
+    ad.name = name;
+
+    int result = selinux_check_access(sctx, tctx, class, perm, (void *) &ad);
     allowed = (result == 0);
 
     freecon(sctx);
     return allowed;
 }
 
-static bool check_mac_perms_from_getcon(pid_t spid, const char *perm)
+static bool check_mac_perms_from_getcon(pid_t spid, uid_t uid, const char *perm)
 {
     if (selinux_enabled <= 0) {
         return true;
     }
 
-    return check_mac_perms(spid, service_manager_context, perm, NULL);
+    return check_mac_perms(spid, uid, service_manager_context, perm, NULL);
 }
 
-static bool check_mac_perms_from_lookup(pid_t spid, const char *perm, const char *name)
+static bool check_mac_perms_from_lookup(pid_t spid, uid_t uid, const char *perm, const char *name)
 {
     bool allowed;
     char *tctx = NULL;
@@ -102,27 +113,27 @@
         return false;
     }
 
-    allowed = check_mac_perms(spid, tctx, perm, name);
+    allowed = check_mac_perms(spid, uid, tctx, perm, name);
     freecon(tctx);
     return allowed;
 }
 
-static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid)
+static int svc_can_register(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
 {
     const char *perm = "add";
-    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
+    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
 }
 
-static int svc_can_list(pid_t spid)
+static int svc_can_list(pid_t spid, uid_t uid)
 {
     const char *perm = "list";
-    return check_mac_perms_from_getcon(spid, perm) ? 1 : 0;
+    return check_mac_perms_from_getcon(spid, uid, perm) ? 1 : 0;
 }
 
-static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid)
+static int svc_can_find(const uint16_t *name, size_t name_len, pid_t spid, uid_t uid)
 {
     const char *perm = "find";
-    return check_mac_perms_from_lookup(spid, perm, str8(name, name_len)) ? 1 : 0;
+    return check_mac_perms_from_lookup(spid, uid, perm, str8(name, name_len)) ? 1 : 0;
 }
 
 struct svcinfo
@@ -167,7 +178,7 @@
 };
 
 
-uint32_t do_find_service(struct binder_state *bs, const uint16_t *s, size_t len, uid_t uid, pid_t spid)
+uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
 {
     struct svcinfo *si = find_svc(s, len);
 
@@ -184,7 +195,7 @@
         }
     }
 
-    if (!svc_can_find(s, len, spid)) {
+    if (!svc_can_find(s, len, spid, uid)) {
         return 0;
     }
 
@@ -204,7 +215,7 @@
     if (!handle || (len == 0) || (len > 127))
         return -1;
 
-    if (!svc_can_register(s, len, spid)) {
+    if (!svc_can_register(s, len, spid, uid)) {
         ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
              str8(s, len), handle, uid);
         return -1;
@@ -293,7 +304,7 @@
         if (s == NULL) {
             return -1;
         }
-        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
+        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
         if (!handle)
             break;
         bio_put_ref(reply, handle);
@@ -314,7 +325,7 @@
     case SVC_MGR_LIST_SERVICES: {
         uint32_t n = bio_get_uint32(msg);
 
-        if (!svc_can_list(txn->sender_pid)) {
+        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
             ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                     txn->sender_euid);
             return -1;
@@ -338,13 +349,20 @@
 }
 
 
-static int audit_callback(void *data, security_class_t cls, char *buf, size_t len)
+static int audit_callback(void *data, __unused security_class_t cls, char *buf, size_t len)
 {
-    snprintf(buf, len, "service=%s", !data ? "NULL" : (char *)data);
+    struct audit_data *ad = (struct audit_data *)data;
+
+    if (!ad || !ad->name) {
+        ALOGE("No service manager audit data");
+        return 0;
+    }
+
+    snprintf(buf, len, "service=%s pid=%d uid=%d", ad->name, ad->pid, ad->uid);
     return 0;
 }
 
-int main(int argc, char **argv)
+int main()
 {
     struct binder_state *bs;
 
diff --git a/cmds/servicemanager/servicemanager.rc b/cmds/servicemanager/servicemanager.rc
new file mode 100644
index 0000000..aee7bd8
--- /dev/null
+++ b/cmds/servicemanager/servicemanager.rc
@@ -0,0 +1,15 @@
+service servicemanager /system/bin/servicemanager
+    class core
+    user system
+    group system readproc
+    critical
+    onrestart restart healthd
+    onrestart restart zygote
+    onrestart restart audioserver
+    onrestart restart media
+    onrestart restart surfaceflinger
+    onrestart restart inputflinger
+    onrestart restart drm
+    onrestart restart cameraserver
+    writepid /dev/cpuset/system-background/tasks
+
diff --git a/data/etc/android.hardware.nfc.hcef.xml b/data/etc/android.hardware.nfc.hcef.xml
new file mode 100644
index 0000000..0d03023
--- /dev/null
+++ b/data/etc/android.hardware.nfc.hcef.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This feature indicates that the device supports host-based
+     NFC-F card emulation -->
+<permissions>
+    <feature name="android.hardware.nfc.hcef" />
+</permissions>
diff --git a/data/etc/android.hardware.type.automotive.xml b/data/etc/android.hardware.type.automotive.xml
new file mode 100644
index 0000000..a9b4b05
--- /dev/null
+++ b/data/etc/android.hardware.type.automotive.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     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.
+-->
+
+<!-- These features determine that the device running android is a car. -->
+<permissions>
+    <feature name="android.hardware.type.automotive" />
+</permissions>
diff --git a/data/etc/android.hardware.vr.high_performance.xml b/data/etc/android.hardware.vr.high_performance.xml
new file mode 100644
index 0000000..776f4f7
--- /dev/null
+++ b/data/etc/android.hardware.vr.high_performance.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This is the set of features required for a VR-compatible device -->
+<permissions>
+    <feature name="android.software.vr.mode" />
+    <feature name="android.hardware.vr.high_performance" />
+</permissions>
diff --git a/data/etc/android.hardware.vulkan.level-0.xml b/data/etc/android.hardware.vulkan.level-0.xml
new file mode 100644
index 0000000..39c65ac
--- /dev/null
+++ b/data/etc/android.hardware.vulkan.level-0.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This is the standard feature indicating that the device supports Vulkan
+     hardware level 0. -->
+<permissions>
+    <feature name="android.hardware.vulkan.level" version="0" />
+</permissions>
diff --git a/data/etc/android.hardware.vulkan.level-1.xml b/data/etc/android.hardware.vulkan.level-1.xml
new file mode 100644
index 0000000..c3f5513
--- /dev/null
+++ b/data/etc/android.hardware.vulkan.level-1.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This is the standard feature indicating that the device supports Vulkan
+     hardware level 1. -->
+<permissions>
+    <feature name="android.hardware.vulkan.level" version="1" />
+</permissions>
diff --git a/data/etc/android.hardware.vulkan.version-1_0_3.xml b/data/etc/android.hardware.vulkan.version-1_0_3.xml
new file mode 100644
index 0000000..adc5a5d
--- /dev/null
+++ b/data/etc/android.hardware.vulkan.version-1_0_3.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2016 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This is the standard feature indicating that the device has a Vulkan
+     driver that supports API version 1.0.3 (0x00400003) -->
+<permissions>
+    <feature name="android.hardware.vulkan.version" version="4194307" />
+</permissions>
diff --git a/data/etc/android.hardware.wifi.nan.xml b/data/etc/android.hardware.wifi.nan.xml
new file mode 100644
index 0000000..e557610
--- /dev/null
+++ b/data/etc/android.hardware.wifi.nan.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This is the standard feature indicating that the device includes WiFi NAN. -->
+<permissions>
+    <feature name="android.hardware.wifi.nan" />
+</permissions>
diff --git a/data/etc/android.software.freeform_window_management.xml b/data/etc/android.software.freeform_window_management.xml
new file mode 100644
index 0000000..58512dc
--- /dev/null
+++ b/data/etc/android.software.freeform_window_management.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     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.
+-->
+
+<permissions>
+    <feature name="android.software.freeform_window_management" />
+</permissions>
diff --git a/data/etc/android.software.picture_in_picture.xml b/data/etc/android.software.picture_in_picture.xml
new file mode 100644
index 0000000..d5e058d
--- /dev/null
+++ b/data/etc/android.software.picture_in_picture.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     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.
+-->
+
+<permissions>
+    <feature name="android.software.picture_in_picture" />
+</permissions>
diff --git a/data/etc/android.software.vr.xml b/data/etc/android.software.vr.xml
new file mode 100644
index 0000000..c7680ec
--- /dev/null
+++ b/data/etc/android.software.vr.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     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.
+-->
+
+<!-- This is the set of features required for a VR-compatible device -->
+<permissions>
+    <feature name="android.software.vr.mode" />
+</permissions>
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
new file mode 100644
index 0000000..ab89ef5
--- /dev/null
+++ b/data/etc/car_core_hardware.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     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.
+-->
+
+<!-- These are the hardware components that all handheld devices
+     must include. Devices with optional hardware must also include extra
+     hardware files, per the comments below.
+
+     Handheld devices include phones, mobile Internet devices (MIDs),
+     Personal Media Players (PMPs), small tablets (7" or less), and similar
+     devices.
+-->
+<permissions>
+    <feature name="android.hardware.audio.output" />
+    <feature name="android.hardware.location" />
+    <feature name="android.hardware.location.network" />
+    <feature name="android.hardware.bluetooth" />
+    <feature name="android.hardware.touchscreen" />
+    <feature name="android.hardware.microphone" />
+    <!-- Feature to specify if the device is a car -->
+    <feature name="android.hardware.type.automotive" />
+
+    <!-- basic system services -->
+    <feature name="android.software.app_widgets" />
+    <feature name="android.software.connectionservice" />
+    <feature name="android.software.voice_recognizers" notLowRam="true" />
+    <feature name="android.software.backup" />
+    <feature name="android.software.home_screen" />
+    <feature name="android.software.input_methods" />
+    <feature name="android.software.print" />
+
+    <!-- Feature to specify if the device supports adding device admins. -->
+    <feature name="android.software.device_admin" />
+
+    <!-- Feature to specify if the device support managed users. -->
+    <feature name="android.software.managed_users" />
+
+    <!-- devices with GPS must include android.hardware.location.gps.xml -->
+    <!-- devices with an autofocus camera and/or flash must include either
+         android.hardware.camera.autofocus.xml or
+         android.hardware.camera.autofocus-flash.xml -->
+    <!-- devices with a front facing camera must include
+         android.hardware.camera.front.xml -->
+    <!-- devices with WiFi must also include android.hardware.wifi.xml -->
+    <!-- devices that support multitouch must include the most appropriate one
+         of these files:
+
+         If only partial (non-independent) pointers are supported:
+         android.hardware.touchscreen.multitouch.xml
+
+         If up to 4 independently tracked pointers are supported:
+         include android.hardware.touchscreen.multitouch.distinct.xml
+
+         If 5 or more independently tracked pointers are supported:
+         include android.hardware.touchscreen.multitouch.jazzhand.xml
+
+         ONLY ONE of the above should be included. -->
+    <!-- devices with an ambient light sensor must also include
+         android.hardware.sensor.light.xml -->
+    <!-- devices with a proximity sensor must also include
+         android.hardware.sensor.proximity.xml -->
+    <!-- GSM phones must also include android.hardware.telephony.gsm.xml -->
+    <!-- CDMA phones must also include android.hardware.telephony.cdma.xml -->
+    <!-- Devices that have low-latency audio stacks suitable for apps like
+         VoIP may include android.hardware.audio.low_latency.xml. ONLY apps
+         that meet the requirements specified in the CDD may include this. -->
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 50cbe9e..9cb4d6d 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -50,6 +50,12 @@
     <!-- Feature to specify if the device support managed users. -->
     <feature name="android.software.managed_users" />
 
+    <!-- Feature to specify if the device supports a VR mode. -->
+    <feature name="android.software.vr.mode" />
+    <!-- Devices with all optimizations required to be a "VR Ready" device that
+         pass all CTS tests for this feature must include feature
+         android.hardware.vr.high_performance -->
+
     <!-- devices with GPS must include android.hardware.location.gps.xml -->
     <!-- devices with an autofocus camera and/or flash must include either
          android.hardware.camera.autofocus.xml or
diff --git a/data/etc/wearable_core_hardware.xml b/data/etc/wearable_core_hardware.xml
index 7c9e8ef..4b7a706 100644
--- a/data/etc/wearable_core_hardware.xml
+++ b/data/etc/wearable_core_hardware.xml
@@ -32,8 +32,10 @@
     <!-- basic system services -->
     <feature name="android.software.home_screen" />
 
-    <!-- devices that support a device administrator policy must include
-         android.software.device_admin.xml -->
+    <!-- device administration -->
+    <feature name="android.software.device_admin" />
+    <feature name="android.software.managed_users" />
+
     <!-- devices with GPS must include device/google/clockwork/gps.xml -->
     <!-- devices with an autofocus camera and/or flash must include either
          android.hardware.camera.autofocus.xml or
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
new file mode 100644
index 0000000..02c83dc
--- /dev/null
+++ b/include/android/choreographer.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/**
+ * @addtogroup Choreographer
+ * @{
+ */
+
+/**
+ * @file choreographer.h
+ */
+
+#ifndef ANDROID_CHOREOGRAPHER_H
+#define ANDROID_CHOREOGRAPHER_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+struct AChoreographer;
+typedef struct AChoreographer AChoreographer;
+
+/**
+ * Prototype of the function that is called when a new frame is being rendered.
+ * It's passed the time that the frame is being rendered as nanoseconds in the
+ * CLOCK_MONOTONIC time base, as well as the data pointer provided by the
+ * application that registered a callback. All callbacks that run as part of
+ * rendering a frame will observe the same frame time, so it should be used
+ * whenever events need to be synchronized (e.g. animations).
+ */
+typedef void (*AChoreographer_frameCallback)(long frameTimeNanos, void* data);
+
+/**
+ * Get the AChoreographer instance for the current thread. This must be called
+ * on an ALooper thread.
+ */
+AChoreographer* AChoreographer_getInstance();
+
+/**
+ * Post a callback to be run on the next frame. The data pointer provided will
+ * be passed to the callback function when it's called.
+ */
+void AChoreographer_postFrameCallback(AChoreographer* choreographer,
+                AChoreographer_frameCallback callback, void* data);
+/**
+ * Post a callback to be run on the frame following the specified delay. The
+ * data pointer provided will be passed to the callback function when it's
+ * called.
+ */
+void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
+                AChoreographer_frameCallback callback, void* data, long delayMillis);
+__END_DECLS
+
+#endif // ANDROID_CHOREOGRAPHER_H
+
+/** @} */
diff --git a/include/android/input.h b/include/android/input.h
index 5ab4e29..fd9fa98 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -644,6 +644,28 @@
      */
     AMOTION_EVENT_AXIS_TILT = 25,
     /**
+     * Axis constant:  Generic scroll axis of a motion event.
+     *
+     * - This is used for scroll axis motion events that can't be classified as strictly
+     *   vertical or horizontal. The movement of a rotating scroller is an example of this.
+     */
+    AMOTION_EVENT_AXIS_SCROLL = 26,
+    /**
+     * Axis constant: The movement of x position of a motion event.
+     *
+     * - For a mouse, reports a difference of x position between the previous position.
+     * This is useful when pointer is captured, in that case the mouse pointer doesn't
+     * change the location but this axis reports the difference which allows the app
+     * to see how the mouse is moved.
+     */
+    AMOTION_EVENT_AXIS_RELATIVE_X = 27,
+    /**
+     * Axis constant: The movement of y position of a motion event.
+     *
+     * Same as {@link RELATIVE_X}, but for y position.
+     */
+    AMOTION_EVENT_AXIS_RELATIVE_Y = 28,
+    /**
      * Axis constant: Generic 1 axis of a motion event.
      * The interpretation of a generic axis is device-specific.
      */
@@ -817,6 +839,8 @@
     AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
     /** joystick */
     AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+    /** rotary encoder */
+    AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
 
     /** any */
     AINPUT_SOURCE_ANY = 0xffffff00,
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 421abe5..67e28da 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -732,12 +732,32 @@
     AKEYCODE_STEM_2 = 266,
     /** Generic stem key 3 for Wear */
     AKEYCODE_STEM_3 = 267,
+    /** Directional Pad Up-Left */
+    AKEYCODE_DPAD_UP_LEFT    = 268,
+    /** Directional Pad Down-Left */
+    AKEYCODE_DPAD_DOWN_LEFT  = 269,
+    /** Directional Pad Up-Right */
+    AKEYCODE_DPAD_UP_RIGHT   = 270,
+    /** Directional Pad Down-Right */
+    AKEYCODE_DPAD_DOWN_RIGHT = 271,
+    /** Skip forward media key */
     AKEYCODE_MEDIA_SKIP_FORWARD = 272,
+    /** Skip backward media key */
     AKEYCODE_MEDIA_SKIP_BACKWARD = 273,
+    /** Step forward media key.
+     * Steps media forward one from at a time. */
     AKEYCODE_MEDIA_STEP_FORWARD = 274,
+    /** Step backward media key.
+     * Steps media backward one from at a time. */
     AKEYCODE_MEDIA_STEP_BACKWARD = 275,
     /** Put device to sleep unless a wakelock is held. */
-    AKEYCODE_SOFT_SLEEP = 276
+    AKEYCODE_SOFT_SLEEP = 276,
+    /** Cut key. */
+    AKEYCODE_CUT = 277,
+    /** Copy key. */
+    AKEYCODE_COPY = 278,
+    /** Paste key. */
+    AKEYCODE_PASTE = 279
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/android/sensor.h b/include/android/sensor.h
index 73928ea..5a61213 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -59,7 +59,7 @@
 
 /**
  * Sensor types.
- * (keep in sync with hardware/sensor.h)
+ * (keep in sync with hardware/sensors.h)
  */
 enum {
     /**
@@ -69,7 +69,7 @@
      *  All values are in SI units (m/s^2) and measure the acceleration of the
      *  device minus the force of gravity.
      */
-    ASENSOR_TYPE_ACCELEROMETER      = 1,
+    ASENSOR_TYPE_ACCELEROMETER       = 1,
     /**
      * {@link ASENSOR_TYPE_MAGNETIC_FIELD}
      * reporting-mode: continuous
@@ -77,7 +77,7 @@
      *  All values are in micro-Tesla (uT) and measure the geomagnetic
      *  field in the X, Y and Z axis.
      */
-    ASENSOR_TYPE_MAGNETIC_FIELD     = 2,
+    ASENSOR_TYPE_MAGNETIC_FIELD      = 2,
     /**
      * {@link ASENSOR_TYPE_GYROSCOPE}
      * reporting-mode: continuous
@@ -85,14 +85,14 @@
      *  All values are in radians/second and measure the rate of rotation
      *  around the X, Y and Z axis.
      */
-    ASENSOR_TYPE_GYROSCOPE          = 4,
+    ASENSOR_TYPE_GYROSCOPE           = 4,
     /**
      * {@link ASENSOR_TYPE_LIGHT}
      * reporting-mode: on-change
      *
      * The light sensor value is returned in SI lux units.
      */
-    ASENSOR_TYPE_LIGHT              = 5,
+    ASENSOR_TYPE_LIGHT               = 5,
     /**
      * {@link ASENSOR_TYPE_PROXIMITY}
      * reporting-mode: on-change
@@ -103,7 +103,15 @@
      * SENSOR_FLAG_WAKE_UP.
      * The value corresponds to the distance to the nearest object in centimeters.
      */
-    ASENSOR_TYPE_PROXIMITY          = 8
+    ASENSOR_TYPE_PROXIMITY           = 8,
+    /**
+     * {@link ASENSOR_TYPE_LINEAR_ACCELERATION}
+     * reporting-mode: continuous
+     *
+     *  All values are in SI units (m/s^2) and measure the acceleration of the
+     *  device not including the force of gravity.
+     */
+    ASENSOR_TYPE_LINEAR_ACCELERATION = 10
 };
 
 /**
@@ -176,29 +184,43 @@
 } AMetaDataEvent;
 
 typedef struct AUncalibratedEvent {
-  union {
-    float uncalib[3];
-    struct {
-      float x_uncalib;
-      float y_uncalib;
-      float z_uncalib;
+    union {
+        float uncalib[3];
+        struct {
+            float x_uncalib;
+            float y_uncalib;
+            float z_uncalib;
+        };
     };
-  };
-  union {
-    float bias[3];
-    struct {
-      float x_bias;
-      float y_bias;
-      float z_bias;
+    union {
+        float bias[3];
+        struct {
+            float x_bias;
+            float y_bias;
+            float z_bias;
+        };
     };
-  };
 } AUncalibratedEvent;
 
 typedef struct AHeartRateEvent {
-  float bpm;
-  int8_t status;
+    float bpm;
+    int8_t status;
 } AHeartRateEvent;
 
+typedef struct ADynamicSensorEvent {
+    int32_t  connected;
+    int32_t  handle;
+} ADynamicSensorEvent;
+
+typedef struct {
+    int32_t type;
+    int32_t serial;
+    union {
+        int32_t data_int32[14];
+        float   data_float[14];
+    };
+} AAdditionalInfoEvent;
+
 /* NOTE: Must match hardware/sensors.h */
 typedef struct ASensorEvent {
     int32_t version; /* sizeof(struct ASensorEvent) */
@@ -221,6 +243,8 @@
             AUncalibratedEvent uncalibrated_magnetic;
             AMetaDataEvent meta_data;
             AHeartRateEvent heart_rate;
+            ADynamicSensorEvent dynamic_sensor_meta;
+            AAdditionalInfoEvent additional_info;
         };
         union {
             uint64_t        data[8];
@@ -369,6 +393,13 @@
 /*****************************************************************************/
 
 /**
+ * Enable the selected sensor with a specified sampling period and max batch report latency.
+ * Returns a negative error code on failure.
+ */
+int ASensorEventQueue_registerSensor(ASensorEventQueue* queue, ASensor const* sensor,
+        int32_t samplingPeriodUs, int maxBatchReportLatencyUs);
+
+/**
  * Enable the selected sensor. Returns a negative error code on failure.
  */
 int ASensorEventQueue_enableSensor(ASensorEventQueue* queue, ASensor const* sensor);
diff --git a/include/batteryservice/BatteryService.h b/include/batteryservice/BatteryService.h
index f0a2790..b399905 100644
--- a/include/batteryservice/BatteryService.h
+++ b/include/batteryservice/BatteryService.h
@@ -58,12 +58,17 @@
     bool chargerUsbOnline;
     bool chargerWirelessOnline;
     int maxChargingCurrent;
+    int maxChargingVoltage;
     int batteryStatus;
     int batteryHealth;
     bool batteryPresent;
     int batteryLevel;
     int batteryVoltage;
     int batteryTemperature;
+    int batteryCurrent;
+    int batteryCycleCount;
+    int batteryFullCharge;
+    int batteryChargeCounter;
     String8 batteryTechnology;
 
     status_t writeToParcel(Parcel* parcel) const;
diff --git a/include/binder/Binder.h b/include/binder/Binder.h
index 86628a0..f849fd4 100644
--- a/include/binder/Binder.h
+++ b/include/binder/Binder.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_BINDER_H
 #define ANDROID_BINDER_H
 
-#include <stdatomic.h>
+#include <atomic>
 #include <stdint.h>
 #include <binder/IBinder.h>
 
@@ -71,7 +71,7 @@
 
     class Extras;
 
-    atomic_uintptr_t    mExtras;  // should be atomic<Extras *>
+    std::atomic<Extras*> mExtras;
             void*       mReserved0;
 };
 
@@ -95,7 +95,7 @@
 
     IBinder* const          mRemote;
     RefBase::weakref_type*  mRefs;
-    volatile int32_t        mState;
+    std::atomic<int32_t>    mState;
 };
 
 }; // namespace android
diff --git a/include/binder/IBinder.h b/include/binder/IBinder.h
index 43b6543..5f1e87c 100644
--- a/include/binder/IBinder.h
+++ b/include/binder/IBinder.h
@@ -23,8 +23,12 @@
 #include <utils/Vector.h>
 
 
+// linux/binder.h already defines this, but we can't just include it from there
+// because there are host builds that include this file.
+#ifndef B_PACK_CHARS
 #define B_PACK_CHARS(c1, c2, c3, c4) \
     ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
+#endif  // B_PACK_CHARS
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -33,6 +37,7 @@
 class BpBinder;
 class IInterface;
 class Parcel;
+class IResultReceiver;
 
 /**
  * Base class and low-level protocol for a remotable object.
@@ -50,6 +55,7 @@
 
         PING_TRANSACTION        = B_PACK_CHARS('_','P','N','G'),
         DUMP_TRANSACTION        = B_PACK_CHARS('_','D','M','P'),
+        SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
         INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
         SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
 
@@ -75,6 +81,9 @@
     virtual bool            isBinderAlive() const = 0;
     virtual status_t        pingBinder() = 0;
     virtual status_t        dump(int fd, const Vector<String16>& args) = 0;
+    static  status_t        shellCommand(const sp<IBinder>& target, int in, int out, int err,
+                                         Vector<String16>& args,
+                                         const sp<IResultReceiver>& resultReceiver);
 
     virtual status_t        transact(   uint32_t code,
                                         const Parcel& data,
diff --git a/include/binder/IMediaResourceMonitor.h b/include/binder/IMediaResourceMonitor.h
new file mode 100644
index 0000000..c671f7a
--- /dev/null
+++ b/include/binder/IMediaResourceMonitor.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_I_MEDIA_RESOURCE_MONITOR_H
+#define ANDROID_I_MEDIA_RESOURCE_MONITOR_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IMediaResourceMonitor : public IInterface {
+public:
+    DECLARE_META_INTERFACE(MediaResourceMonitor);
+
+    // Values should be in sync with Intent.EXTRA_MEDIA_RESOURCE_TYPE_XXX.
+    enum {
+        TYPE_VIDEO_CODEC = 0,
+        TYPE_AUDIO_CODEC = 1,
+    };
+
+    virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type) = 0;
+
+    enum {
+        NOTIFY_RESOURCE_GRANTED = IBinder::FIRST_CALL_TRANSACTION,
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnMediaResourceMonitor : public BnInterface<IMediaResourceMonitor> {
+public:
+    virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
+            uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_I_MEDIA_RESOURCE_MONITOR_H
diff --git a/include/binder/IProcessInfoService.h b/include/binder/IProcessInfoService.h
index dc62f45..69dc9a7 100644
--- a/include/binder/IProcessInfoService.h
+++ b/include/binder/IProcessInfoService.h
@@ -31,23 +31,19 @@
                                                   /*in*/ int32_t* pids,
                                                   /*out*/ int32_t* states) = 0;
 
+    virtual status_t    getProcessStatesAndOomScoresFromPids( size_t length,
+                                                  /*in*/ int32_t* pids,
+                                                  /*out*/ int32_t* states,
+                                                  /*out*/ int32_t* scores) = 0;
+
     enum {
         GET_PROCESS_STATES_FROM_PIDS = IBinder::FIRST_CALL_TRANSACTION,
+        GET_PROCESS_STATES_AND_OOM_SCORES_FROM_PIDS,
     };
 };
 
 // ----------------------------------------------------------------------
 
-class BnProcessInfoService : public BnInterface<IProcessInfoService> {
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------
-
 }; // namespace android
 
 #endif // ANDROID_I_PROCESS_INFO_SERVICE_H
diff --git a/include/binder/IResultReceiver.h b/include/binder/IResultReceiver.h
new file mode 100644
index 0000000..02dc6a6
--- /dev/null
+++ b/include/binder/IResultReceiver.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//
+#ifndef ANDROID_IRESULT_RECEIVER_H
+#define ANDROID_IRESULT_RECEIVER_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IResultReceiver : public IInterface
+{
+public:
+    DECLARE_META_INTERFACE(ResultReceiver);
+
+    virtual void send(int32_t resultCode) = 0;
+
+    enum {
+        OP_SEND = IBinder::FIRST_CALL_TRANSACTION
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnResultReceiver : public BnInterface<IResultReceiver>
+{
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_IRESULT_RECEIVER_H
+
diff --git a/include/binder/IServiceManager.h b/include/binder/IServiceManager.h
index 2c297d6..7ccd9fe 100644
--- a/include/binder/IServiceManager.h
+++ b/include/binder/IServiceManager.h
@@ -81,20 +81,6 @@
                             int32_t* outPid, int32_t* outUid);
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
 
-
-// ----------------------------------------------------------------------
-
-class BnServiceManager : public BnInterface<IServiceManager>
-{
-public:
-    virtual status_t    onTransact( uint32_t code,
-                                    const Parcel& data,
-                                    Parcel* reply,
-                                    uint32_t flags = 0);
-};
-
-// ----------------------------------------------------------------------
-
 }; // namespace android
 
 #endif // ANDROID_ISERVICE_MANAGER_H
diff --git a/include/binder/MemoryDealer.h b/include/binder/MemoryDealer.h
index aa415d5..60a624c 100644
--- a/include/binder/MemoryDealer.h
+++ b/include/binder/MemoryDealer.h
@@ -41,6 +41,9 @@
     virtual void        deallocate(size_t offset);
     virtual void        dump(const char* what) const;
 
+    // allocations are aligned to some value. return that value so clients can account for it.
+    static size_t      getAllocationAlignment();
+
     sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
 
 protected:
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 16cd6cf..2685bcc 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -17,7 +17,11 @@
 #ifndef ANDROID_PARCEL_H
 #define ANDROID_PARCEL_H
 
+#include <string>
+#include <vector>
+
 #include <cutils/native_handle.h>
+#include <nativehelper/ScopedFd.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/String16.h>
@@ -25,6 +29,9 @@
 #include <utils/Flattenable.h>
 #include <linux/binder.h>
 
+#include <binder/IInterface.h>
+#include <binder/Parcelable.h>
+
 // ---------------------------------------------------------------------------
 namespace android {
 
@@ -103,11 +110,55 @@
     status_t            writeCString(const char* str);
     status_t            writeString8(const String8& str);
     status_t            writeString16(const String16& str);
+    status_t            writeString16(const std::unique_ptr<String16>& str);
     status_t            writeString16(const char16_t* str, size_t len);
     status_t            writeStrongBinder(const sp<IBinder>& val);
     status_t            writeWeakBinder(const wp<IBinder>& val);
     status_t            writeInt32Array(size_t len, const int32_t *val);
     status_t            writeByteArray(size_t len, const uint8_t *val);
+    status_t            writeBool(bool val);
+    status_t            writeChar(char16_t val);
+    status_t            writeByte(int8_t val);
+
+    // Take a UTF8 encoded string, convert to UTF16, write it to the parcel.
+    status_t            writeUtf8AsUtf16(const std::string& str);
+    status_t            writeUtf8AsUtf16(const std::unique_ptr<std::string>& str);
+
+    status_t            writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val);
+    status_t            writeByteVector(const std::vector<int8_t>& val);
+    status_t            writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val);
+    status_t            writeByteVector(const std::vector<uint8_t>& val);
+    status_t            writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val);
+    status_t            writeInt32Vector(const std::vector<int32_t>& val);
+    status_t            writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val);
+    status_t            writeInt64Vector(const std::vector<int64_t>& val);
+    status_t            writeFloatVector(const std::unique_ptr<std::vector<float>>& val);
+    status_t            writeFloatVector(const std::vector<float>& val);
+    status_t            writeDoubleVector(const std::unique_ptr<std::vector<double>>& val);
+    status_t            writeDoubleVector(const std::vector<double>& val);
+    status_t            writeBoolVector(const std::unique_ptr<std::vector<bool>>& val);
+    status_t            writeBoolVector(const std::vector<bool>& val);
+    status_t            writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val);
+    status_t            writeCharVector(const std::vector<char16_t>& val);
+    status_t            writeString16Vector(
+                            const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val);
+    status_t            writeString16Vector(const std::vector<String16>& val);
+    status_t            writeUtf8VectorAsUtf16Vector(
+                            const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val);
+    status_t            writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
+
+    status_t            writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
+    status_t            writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
+
+    template<typename T>
+    status_t            writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
+    template<typename T>
+    status_t            writeParcelableVector(const std::vector<T>& val);
+
+    template<typename T>
+    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable);
+
+    status_t            writeParcelable(const Parcelable& parcelable);
 
     template<typename T>
     status_t            write(const Flattenable<T>& val);
@@ -118,7 +169,7 @@
 
     // Place a native_handle into the parcel (the native_handle's file-
     // descriptors are dup'ed, so it is safe to delete the native_handle
-    // when this function returns). 
+    // when this function returns).
     // Doesn't take ownership of the native_handle.
     status_t            writeNativeHandle(const native_handle* handle);
     
@@ -131,6 +182,19 @@
     // will be closed once the parcel is destroyed.
     status_t            writeDupFileDescriptor(int fd);
 
+    // Place a file descriptor into the parcel.  This will not affect the
+    // semantics of the smart file descriptor. A new descriptor will be
+    // created, and will be closed when the parcel is destroyed.
+    status_t            writeUniqueFileDescriptor(
+                            const ScopedFd& fd);
+
+    // Place a vector of file desciptors into the parcel. Each descriptor is
+    // dup'd as in writeDupFileDescriptor
+    status_t            writeUniqueFileDescriptorVector(
+                            const std::unique_ptr<std::vector<ScopedFd>>& val);
+    status_t            writeUniqueFileDescriptorVector(
+                            const std::vector<ScopedFd>& val);
+
     // Writes a blob to the parcel.
     // If the blob is small, then it is stored in-place, otherwise it is
     // transferred by way of an anonymous shared memory region.  Prefer sending
@@ -169,15 +233,68 @@
     status_t            readDouble(double *pArg) const;
     intptr_t            readIntPtr() const;
     status_t            readIntPtr(intptr_t *pArg) const;
+    bool                readBool() const;
+    status_t            readBool(bool *pArg) const;
+    char16_t            readChar() const;
+    status_t            readChar(char16_t *pArg) const;
+    int8_t              readByte() const;
+    status_t            readByte(int8_t *pArg) const;
+
+    // Read a UTF16 encoded string, convert to UTF8
+    status_t            readUtf8FromUtf16(std::string* str) const;
+    status_t            readUtf8FromUtf16(std::unique_ptr<std::string>* str) const;
 
     const char*         readCString() const;
     String8             readString8() const;
     String16            readString16() const;
+    status_t            readString16(String16* pArg) const;
+    status_t            readString16(std::unique_ptr<String16>* pArg) const;
     const char16_t*     readString16Inplace(size_t* outLen) const;
     sp<IBinder>         readStrongBinder() const;
+    status_t            readStrongBinder(sp<IBinder>* val) const;
     wp<IBinder>         readWeakBinder() const;
 
     template<typename T>
+    status_t            readParcelableVector(
+                            std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
+    template<typename T>
+    status_t            readParcelableVector(std::vector<T>* val) const;
+
+    status_t            readParcelable(Parcelable* parcelable) const;
+
+    template<typename T>
+    status_t            readParcelable(std::unique_ptr<T>* parcelable) const;
+
+    template<typename T>
+    status_t            readStrongBinder(sp<T>* val) const;
+
+    status_t            readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
+    status_t            readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
+
+    status_t            readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const;
+    status_t            readByteVector(std::vector<int8_t>* val) const;
+    status_t            readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const;
+    status_t            readByteVector(std::vector<uint8_t>* val) const;
+    status_t            readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const;
+    status_t            readInt32Vector(std::vector<int32_t>* val) const;
+    status_t            readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const;
+    status_t            readInt64Vector(std::vector<int64_t>* val) const;
+    status_t            readFloatVector(std::unique_ptr<std::vector<float>>* val) const;
+    status_t            readFloatVector(std::vector<float>* val) const;
+    status_t            readDoubleVector(std::unique_ptr<std::vector<double>>* val) const;
+    status_t            readDoubleVector(std::vector<double>* val) const;
+    status_t            readBoolVector(std::unique_ptr<std::vector<bool>>* val) const;
+    status_t            readBoolVector(std::vector<bool>* val) const;
+    status_t            readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const;
+    status_t            readCharVector(std::vector<char16_t>* val) const;
+    status_t            readString16Vector(
+                            std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const;
+    status_t            readString16Vector(std::vector<String16>* val) const;
+    status_t            readUtf8VectorFromUtf16Vector(
+                            std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const;
+    status_t            readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
+
+    template<typename T>
     status_t            read(Flattenable<T>& val) const;
 
     template<typename T>
@@ -201,6 +318,17 @@
     // in the parcel, which you do not own -- use dup() to get your own copy.
     int                 readFileDescriptor() const;
 
+    // Retrieve a smart file descriptor from the parcel.
+    status_t            readUniqueFileDescriptor(
+                            ScopedFd* val) const;
+
+
+    // Retrieve a vector of smart file descriptors from the parcel.
+    status_t            readUniqueFileDescriptorVector(
+                            std::unique_ptr<std::vector<ScopedFd>>* val) const;
+    status_t            readUniqueFileDescriptorVector(
+                            std::vector<ScopedFd>* val) const;
+
     // Reads a blob from the parcel.
     // The caller should call release() on the blob after reading its contents.
     status_t            readBlob(size_t len, ReadableBlob* outBlob) const;
@@ -256,6 +384,34 @@
     template<class T>
     status_t            writeAligned(T val);
 
+    status_t            writeRawNullableParcelable(const Parcelable*
+                                                   parcelable);
+
+    template<typename T, typename U>
+    status_t            unsafeReadTypedVector(std::vector<T>* val,
+                                              status_t(Parcel::*read_func)(U*) const) const;
+    template<typename T>
+    status_t            readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
+                                                status_t(Parcel::*read_func)(T*) const) const;
+    template<typename T>
+    status_t            readTypedVector(std::vector<T>* val,
+                                        status_t(Parcel::*read_func)(T*) const) const;
+    template<typename T, typename U>
+    status_t            unsafeWriteTypedVector(const std::vector<T>& val,
+                                               status_t(Parcel::*write_func)(U));
+    template<typename T>
+    status_t            writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+                                                 status_t(Parcel::*write_func)(const T&));
+    template<typename T>
+    status_t            writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+                                                 status_t(Parcel::*write_func)(T));
+    template<typename T>
+    status_t            writeTypedVector(const std::vector<T>& val,
+                                         status_t(Parcel::*write_func)(const T&));
+    template<typename T>
+    status_t            writeTypedVector(const std::vector<T>& val,
+                                         status_t(Parcel::*write_func)(T));
+
     status_t            mError;
     uint8_t*            mData;
     size_t              mDataSize;
@@ -269,7 +425,7 @@
     mutable bool        mFdsKnown;
     mutable bool        mHasFds;
     bool                mAllowFds;
-    
+
     release_func        mOwner;
     void*               mOwnerCookie;
 
@@ -402,6 +558,206 @@
     return NO_ERROR;
 }
 
+template<typename T>
+status_t Parcel::readStrongBinder(sp<T>* val) const {
+    sp<IBinder> tmp;
+    status_t ret = readStrongBinder(&tmp);
+
+    if (ret == OK) {
+        *val = interface_cast<T>(tmp);
+
+        if (val->get() == nullptr) {
+            return UNKNOWN_ERROR;
+        }
+    }
+
+    return ret;
+}
+
+template<typename T, typename U>
+status_t Parcel::unsafeReadTypedVector(
+        std::vector<T>* val,
+        status_t(Parcel::*read_func)(U*) const) const {
+    int32_t size;
+    status_t status = this->readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return UNEXPECTED_NULL;
+    }
+
+    val->resize(size);
+
+    for (auto& v: *val) {
+        status = (this->*read_func)(&v);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+template<typename T>
+status_t Parcel::readTypedVector(std::vector<T>* val,
+                                 status_t(Parcel::*read_func)(T*) const) const {
+    return unsafeReadTypedVector(val, read_func);
+}
+
+template<typename T>
+status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
+                                         status_t(Parcel::*read_func)(T*) const) const {
+    const int32_t start = dataPosition();
+    int32_t size;
+    status_t status = readInt32(&size);
+    val->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    setDataPosition(start);
+    val->reset(new std::vector<T>());
+
+    status = unsafeReadTypedVector(val->get(), read_func);
+
+    if (status != OK) {
+        val->reset();
+    }
+
+    return status;
+}
+
+template<typename T, typename U>
+status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val,
+                                        status_t(Parcel::*write_func)(U)) {
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t status = this->writeInt32(val.size());
+
+    if (status != OK) {
+        return status;
+    }
+
+    for (const auto& item : val) {
+        status = (this->*write_func)(item);
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+template<typename T>
+status_t Parcel::writeTypedVector(const std::vector<T>& val,
+                                  status_t(Parcel::*write_func)(const T&)) {
+    return unsafeWriteTypedVector(val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeTypedVector(const std::vector<T>& val,
+                                  status_t(Parcel::*write_func)(T)) {
+    return unsafeWriteTypedVector(val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+                                          status_t(Parcel::*write_func)(const T&)) {
+    if (val.get() == nullptr) {
+        return this->writeInt32(-1);
+    }
+
+    return unsafeWriteTypedVector(*val, write_func);
+}
+
+template<typename T>
+status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
+                                          status_t(Parcel::*write_func)(T)) {
+    if (val.get() == nullptr) {
+        return this->writeInt32(-1);
+    }
+
+    return unsafeWriteTypedVector(*val, write_func);
+}
+
+template<typename T>
+status_t Parcel::readParcelableVector(std::vector<T>* val) const {
+    return unsafeReadTypedVector<T, Parcelable>(val, &Parcel::readParcelable);
+}
+
+template<typename T>
+status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const {
+    const int32_t start = dataPosition();
+    int32_t size;
+    status_t status = readInt32(&size);
+    val->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    setDataPosition(start);
+    val->reset(new std::vector<T>());
+
+    status = unsafeReadTypedVector(val->get(), &Parcel::readParcelable);
+
+    if (status != OK) {
+        val->reset();
+    }
+
+    return status;
+}
+
+template<typename T>
+status_t Parcel::readParcelable(std::unique_ptr<T>* parcelable) const {
+    const int32_t start = dataPosition();
+    int32_t present;
+    status_t status = readInt32(&present);
+    parcelable->reset();
+
+    if (status != OK || !present) {
+        return status;
+    }
+
+    setDataPosition(start);
+    parcelable->reset(new T());
+
+    status = readParcelable(parcelable->get());
+
+    if (status != OK) {
+        parcelable->reset();
+    }
+
+    return status;
+}
+
+template<typename T>
+status_t Parcel::writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
+    return writeRawNullableParcelable(parcelable.get());
+}
+
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::vector<T>& val) {
+    return unsafeWriteTypedVector<T,const Parcelable&>(val, &Parcel::writeParcelable);
+}
+
+template<typename T>
+status_t Parcel::writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) {
+    if (val.get() == nullptr) {
+        return this->writeInt32(-1);
+    }
+
+    return unsafeWriteTypedVector(*val, &Parcel::writeParcelable);
+}
+
 // ---------------------------------------------------------------------------
 
 inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
diff --git a/include/binder/Parcelable.h b/include/binder/Parcelable.h
new file mode 100644
index 0000000..faf0d34
--- /dev/null
+++ b/include/binder/Parcelable.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_PARCELABLE_H
+#define ANDROID_PARCELABLE_H
+
+#include <vector>
+
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+
+class Parcel;
+
+// Abstract interface of all parcelables.
+class Parcelable {
+public:
+    virtual ~Parcelable() = default;
+
+    // Write |this| parcelable to the given |parcel|.  Keep in mind that
+    // implementations of writeToParcel must be manually kept in sync
+    // with readFromParcel and the Java equivalent versions of these methods.
+    //
+    // Returns android::OK on success and an appropriate error otherwise.
+    virtual status_t writeToParcel(Parcel* parcel) const = 0;
+
+    // Read data from the given |parcel| into |this|.  After readFromParcel
+    // completes, |this| should have equivalent state to the object that
+    // wrote itself to the parcel.
+    //
+    // Returns android::OK on success and an appropriate error otherwise.
+    virtual status_t readFromParcel(const Parcel* parcel) = 0;
+};  // class Parcelable
+
+}  // namespace android
+
+#endif // ANDROID_PARCELABLE_H
diff --git a/include/binder/PersistableBundle.h b/include/binder/PersistableBundle.h
new file mode 100644
index 0000000..fe5619f
--- /dev/null
+++ b/include/binder/PersistableBundle.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_PERSISTABLE_BUNDLE_H
+#define ANDROID_PERSISTABLE_BUNDLE_H
+
+#include <map>
+#include <vector>
+
+#include <binder/Parcelable.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+namespace os {
+
+/*
+ * C++ implementation of PersistableBundle, a mapping from String values to
+ * various types that can be saved to persistent and later restored.
+ */
+class PersistableBundle : public Parcelable {
+public:
+    PersistableBundle() = default;
+    virtual ~PersistableBundle() = default;
+    PersistableBundle(const PersistableBundle& bundle) = default;
+
+    status_t writeToParcel(Parcel* parcel) const override;
+    status_t readFromParcel(const Parcel* parcel) override;
+
+    bool empty() const;
+    size_t size() const;
+    size_t erase(const String16& key);
+
+    /*
+     * Setters for PersistableBundle. Adds a a key-value pair instantiated with
+     * |key| and |value| into the member map appropriate for the type of |value|.
+     * If there is already an existing value for |key|, |value| will replace it.
+     */
+    void putBoolean(const String16& key, bool value);
+    void putInt(const String16& key, int32_t value);
+    void putLong(const String16& key, int64_t value);
+    void putDouble(const String16& key, double value);
+    void putString(const String16& key, const String16& value);
+    void putBooleanVector(const String16& key, const std::vector<bool>& value);
+    void putIntVector(const String16& key, const std::vector<int32_t>& value);
+    void putLongVector(const String16& key, const std::vector<int64_t>& value);
+    void putDoubleVector(const String16& key, const std::vector<double>& value);
+    void putStringVector(const String16& key, const std::vector<String16>& value);
+    void putPersistableBundle(const String16& key, const PersistableBundle& value);
+
+    /*
+     * Getters for PersistableBundle. If |key| exists, these methods write the
+     * value associated with |key| into |out|, and return true. Otherwise, these
+     * methods return false.
+     */
+    bool getBoolean(const String16& key, bool* out) const;
+    bool getInt(const String16& key, int32_t* out) const;
+    bool getLong(const String16& key, int64_t* out) const;
+    bool getDouble(const String16& key, double* out) const;
+    bool getString(const String16& key, String16* out) const;
+    bool getBooleanVector(const String16& key, std::vector<bool>* out) const;
+    bool getIntVector(const String16& key, std::vector<int32_t>* out) const;
+    bool getLongVector(const String16& key, std::vector<int64_t>* out) const;
+    bool getDoubleVector(const String16& key, std::vector<double>* out) const;
+    bool getStringVector(const String16& key, std::vector<String16>* out) const;
+    bool getPersistableBundle(const String16& key, PersistableBundle* out) const;
+
+    friend bool operator==(const PersistableBundle& lhs, const PersistableBundle& rhs) {
+        return (lhs.mBoolMap == rhs.mBoolMap && lhs.mIntMap == rhs.mIntMap &&
+                lhs.mLongMap == rhs.mLongMap && lhs.mDoubleMap == rhs.mDoubleMap &&
+                lhs.mStringMap == rhs.mStringMap && lhs.mBoolVectorMap == rhs.mBoolVectorMap &&
+                lhs.mIntVectorMap == rhs.mIntVectorMap &&
+                lhs.mLongVectorMap == rhs.mLongVectorMap &&
+                lhs.mDoubleVectorMap == rhs.mDoubleVectorMap &&
+                lhs.mStringVectorMap == rhs.mStringVectorMap &&
+                lhs.mPersistableBundleMap == rhs.mPersistableBundleMap);
+    }
+
+    friend bool operator!=(const PersistableBundle& lhs, const PersistableBundle& rhs) {
+        return !(lhs == rhs);
+    }
+
+private:
+    status_t writeToParcelInner(Parcel* parcel) const;
+    status_t readFromParcelInner(const Parcel* parcel, size_t length);
+
+    std::map<String16, bool> mBoolMap;
+    std::map<String16, int32_t> mIntMap;
+    std::map<String16, int64_t> mLongMap;
+    std::map<String16, double> mDoubleMap;
+    std::map<String16, String16> mStringMap;
+    std::map<String16, std::vector<bool>> mBoolVectorMap;
+    std::map<String16, std::vector<int32_t>> mIntVectorMap;
+    std::map<String16, std::vector<int64_t>> mLongVectorMap;
+    std::map<String16, std::vector<double>> mDoubleVectorMap;
+    std::map<String16, std::vector<String16>> mStringVectorMap;
+    std::map<String16, PersistableBundle> mPersistableBundleMap;
+};
+
+}  // namespace os
+
+}  // namespace android
+
+#endif  // ANDROID_PERSISTABLE_BUNDLE_H
diff --git a/include/binder/ProcessState.h b/include/binder/ProcessState.h
index f9edc2a..64cf72e 100644
--- a/include/binder/ProcessState.h
+++ b/include/binder/ProcessState.h
@@ -91,6 +91,8 @@
             size_t              mExecutingThreadsCount;
             // Maximum number for binder threads allowed for this process.
             size_t              mMaxThreads;
+            // Time when thread pool was emptied
+            int64_t             mStarvationStartTimeMs;
 
     mutable Mutex               mLock;  // protects everything below.
 
diff --git a/include/binder/Status.h b/include/binder/Status.h
new file mode 100644
index 0000000..ce947fa
--- /dev/null
+++ b/include/binder/Status.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_BINDER_STATUS_H
+#define ANDROID_BINDER_STATUS_H
+
+#include <cstdint>
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace binder {
+
+// An object similar in function to a status_t except that it understands
+// how exceptions are encoded in the prefix of a Parcel. Used like:
+//
+//     Parcel data;
+//     Parcel reply;
+//     status_t status;
+//     binder::Status remote_exception;
+//     if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
+//         (status = data.writeInt32(function_input)) != OK) {
+//         // We failed to write into the memory of our local parcel?
+//     }
+//     if ((status = remote()->transact(transaction, data, &reply)) != OK) {
+//        // Something has gone wrong in the binder driver or libbinder.
+//     }
+//     if ((status = remote_exception.readFromParcel(reply)) != OK) {
+//         // The remote didn't correctly write the exception header to the
+//         // reply.
+//     }
+//     if (!remote_exception.isOk()) {
+//         // The transaction went through correctly, but the remote reported an
+//         // exception during handling.
+//     }
+//
+class Status final {
+public:
+    // Keep the exception codes in sync with android/os/Parcel.java.
+    enum Exception {
+        EX_NONE = 0,
+        EX_SECURITY = -1,
+        EX_BAD_PARCELABLE = -2,
+        EX_ILLEGAL_ARGUMENT = -3,
+        EX_NULL_POINTER = -4,
+        EX_ILLEGAL_STATE = -5,
+        EX_NETWORK_MAIN_THREAD = -6,
+        EX_UNSUPPORTED_OPERATION = -7,
+        EX_SERVICE_SPECIFIC = -8,
+
+        // This is special and Java specific; see Parcel.java.
+        EX_HAS_REPLY_HEADER = -128,
+        // This is special, and indicates to C++ binder proxies that the
+        // transaction has failed at a low level.
+        EX_TRANSACTION_FAILED = -129,
+    };
+
+    // A more readable alias for the default constructor.
+    static Status ok();
+    // Authors should explicitly pick whether their integer is:
+    //  - an exception code (EX_* above)
+    //  - service specific error code
+    //  - status_t
+    //
+    //  Prefer a generic exception code when possible, then a service specific
+    //  code, and finally a status_t for low level failures or legacy support.
+    //  Exception codes and service specific errors map to nicer exceptions for
+    //  Java clients.
+    static Status fromExceptionCode(int32_t exceptionCode);
+    static Status fromExceptionCode(int32_t exceptionCode,
+                                    const String8& message);
+    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
+    static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
+                                           const String8& message);
+    static Status fromStatusT(status_t status);
+
+    Status() = default;
+    ~Status() = default;
+
+    // Status objects are copyable and contain just simple data.
+    Status(const Status& status) = default;
+    Status(Status&& status) = default;
+    Status& operator=(const Status& status) = default;
+
+    // Bear in mind that if the client or service is a Java endpoint, this
+    // is not the logic which will provide/interpret the data here.
+    status_t readFromParcel(const Parcel& parcel);
+    status_t writeToParcel(Parcel* parcel) const;
+
+    // Set one of the pre-defined exception types defined above.
+    void setException(int32_t ex, const String8& message);
+    // Set a service specific exception with error code.
+    void setServiceSpecificError(int32_t errorCode, const String8& message);
+    // Setting a |status| != OK causes generated code to return |status|
+    // from Binder transactions, rather than writing an exception into the
+    // reply Parcel.  This is the least preferable way of reporting errors.
+    void setFromStatusT(status_t status);
+
+    // Get information about an exception.
+    int32_t exceptionCode() const  { return mException; }
+    const String8& exceptionMessage() const { return mMessage; }
+    status_t transactionError() const {
+        return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
+    }
+    int32_t serviceSpecificErrorCode() const {
+        return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
+    }
+
+    bool isOk() const { return mException == EX_NONE; }
+
+    // For logging.
+    String8 toString8() const;
+
+private:
+    Status(int32_t exceptionCode, int32_t errorCode);
+    Status(int32_t exceptionCode, int32_t errorCode, const String8& message);
+
+    // If |mException| == EX_TRANSACTION_FAILED, generated code will return
+    // |mErrorCode| as the result of the transaction rather than write an
+    // exception to the reply parcel.
+    //
+    // Otherwise, we always write |mException| to the parcel.
+    // If |mException| !=  EX_NONE, we write |mMessage| as well.
+    // If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
+    int32_t mException = EX_NONE;
+    int32_t mErrorCode = 0;
+    String8 mMessage;
+};  // class Status
+
+// For gtest output logging
+template<typename T>
+T& operator<< (T& stream, const Status& s) {
+    stream << s.toString8().string();
+    return stream;
+}
+
+}  // namespace binder
+}  // namespace android
+
+#endif // ANDROID_BINDER_STATUS_H
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 145efe6..f45d852 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -98,13 +98,8 @@
         };
     };
 
-    union {
-        // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
-        int mSlot;
-
-        // mBuf is the former name for mSlot
-        int mBuf;
-    };
+    // mSlot is the slot index of this buffer (default INVALID_BUFFER_SLOT).
+    int mSlot;
 
     // mIsDroppable whether this buffer was queued with the
     // property that it can be replaced by a new buffer for the purpose of
@@ -123,6 +118,19 @@
     // Describes the portion of the surface that has been modified since the
     // previous frame
     Region mSurfaceDamage;
+
+    // Indicates that the consumer should acquire the next frame as soon as it
+    // can and not wait for a frame to become available. This is only relevant
+    // in shared buffer mode.
+    bool mAutoRefresh;
+
+    // Indicates that this buffer was queued by the producer. When in shared
+    // buffer mode acquire() can return a BufferItem that wasn't in the queue.
+    bool mQueuedBuffer;
+
+    // Indicates that this BufferItem contains a stale buffer which has already
+    // been released by the BufferQueue.
+    bool mIsStale;
 };
 
 } // namespace android
diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h
index cde302f..b2daae4 100644
--- a/include/gui/BufferQueueConsumer.h
+++ b/include/gui/BufferQueueConsumer.h
@@ -100,20 +100,8 @@
     // is 1x1.
     virtual status_t setDefaultBufferSize(uint32_t width, uint32_t height);
 
-    // setDefaultMaxBufferCount sets the default value for the maximum buffer
-    // count (the initial default is 2). If the producer has requested a
-    // buffer count using setBufferCount, the default buffer count will only
-    // take effect if the producer sets the count back to zero.
-    //
-    // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
-    virtual status_t setDefaultMaxBufferCount(int bufferCount);
-
-    // disableAsyncBuffer disables the extra buffer used in async mode
-    // (when both producer and consumer have set their "isControlledByApp"
-    // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
-    //
-    // This can only be called before connect().
-    virtual status_t disableAsyncBuffer();
+    // see IGraphicBufferConsumer::setMaxBufferCount
+    virtual status_t setMaxBufferCount(int bufferCount);
 
     // setMaxAcquiredBufferCount sets the maximum number of buffers that can
     // be acquired by the consumer at one time (default 1).  This call will
diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h
index 99134ea..4337da9 100644
--- a/include/gui/BufferQueueCore.h
+++ b/include/gui/BufferQueueCore.h
@@ -67,8 +67,13 @@
     // consumer can run asynchronously.
     enum { MAX_MAX_ACQUIRED_BUFFERS = BufferQueueDefs::NUM_BUFFER_SLOTS - 2 };
 
-    // The default API number used to indicate that no producer is connected
-    enum { NO_CONNECTED_API = 0 };
+    enum {
+        // The API number used to indicate the currently connected producer
+        CURRENTLY_CONNECTED_API = -1,
+
+        // The API number used to indicate that no producer is connected
+        NO_CONNECTED_API        = 0,
+    };
 
     typedef Vector<BufferItem> Fifo;
 
@@ -85,50 +90,52 @@
     // getMinUndequeuedBufferCountLocked returns the minimum number of buffers
     // that must remain in a state other than DEQUEUED. The async parameter
     // tells whether we're in asynchronous mode.
-    int getMinUndequeuedBufferCountLocked(bool async) const;
+    int getMinUndequeuedBufferCountLocked() const;
 
     // getMinMaxBufferCountLocked returns the minimum number of buffers allowed
     // given the current BufferQueue state. The async parameter tells whether
     // we're in asynchonous mode.
-    int getMinMaxBufferCountLocked(bool async) const;
+    int getMinMaxBufferCountLocked() const;
 
     // getMaxBufferCountLocked returns the maximum number of buffers that can be
     // allocated at once. This value depends on the following member variables:
     //
-    //     mDequeueBufferCannotBlock
+    //     mMaxDequeuedBufferCount
     //     mMaxAcquiredBufferCount
-    //     mDefaultMaxBufferCount
-    //     mOverrideMaxBufferCount
-    //     async parameter
+    //     mMaxBufferCount
+    //     mAsyncMode
+    //     mDequeueBufferCannotBlock
     //
     // Any time one of these member variables is changed while a producer is
     // connected, mDequeueCondition must be broadcast.
-    int getMaxBufferCountLocked(bool async) const;
+    int getMaxBufferCountLocked() const;
 
-    // setDefaultMaxBufferCountLocked sets the maximum number of buffer slots
-    // that will be used if the producer does not override the buffer slot
-    // count. The count must be between 2 and NUM_BUFFER_SLOTS, inclusive. The
-    // initial default is 2.
-    status_t setDefaultMaxBufferCountLocked(int count);
+    // This performs the same computation but uses the given arguments instead
+    // of the member variables for mMaxBufferCount, mAsyncMode, and
+    // mDequeueBufferCannotBlock.
+    int getMaxBufferCountLocked(bool asyncMode,
+            bool dequeueBufferCannotBlock, int maxBufferCount) const;
 
-    // freeBufferLocked frees the GraphicBuffer and sync resources for the
+    // clearBufferSlotLocked frees the GraphicBuffer and sync resources for the
     // given slot.
-    void freeBufferLocked(int slot);
+    void clearBufferSlotLocked(int slot);
 
     // freeAllBuffersLocked frees the GraphicBuffer and sync resources for
-    // all slots.
+    // all slots, even if they're currently dequeued, queued, or acquired.
     void freeAllBuffersLocked();
 
-    // stillTracking returns true iff the buffer item is still being tracked
-    // in one of the slots.
-    bool stillTracking(const BufferItem* item) const;
+    // If delta is positive, makes more slots available. If negative, takes
+    // away slots. Returns false if the request can't be met.
+    bool adjustAvailableSlotsLocked(int delta);
 
     // waitWhileAllocatingLocked blocks until mIsAllocating is false.
     void waitWhileAllocatingLocked() const;
 
+#if DEBUG_ONLY_CODE
     // validateConsistencyLocked ensures that the free lists are in sync with
     // the information stored in mSlots
     void validateConsistencyLocked() const;
+#endif
 
     // mAllocator is the connection to SurfaceFlinger that is used to allocate
     // new GraphicBuffer objects.
@@ -185,28 +192,24 @@
     Fifo mQueue;
 
     // mFreeSlots contains all of the slots which are FREE and do not currently
-    // have a buffer attached
+    // have a buffer attached.
     std::set<int> mFreeSlots;
 
     // mFreeBuffers contains all of the slots which are FREE and currently have
-    // a buffer attached
+    // a buffer attached.
     std::list<int> mFreeBuffers;
 
-    // mOverrideMaxBufferCount is the limit on the number of buffers that will
-    // be allocated at one time. This value is set by the producer by calling
-    // setBufferCount. The default is 0, which means that the producer doesn't
-    // care about the number of buffers in the pool. In that case,
-    // mDefaultMaxBufferCount is used as the limit.
-    int mOverrideMaxBufferCount;
+    // mUnusedSlots contains all slots that are currently unused. They should be
+    // free and not have a buffer attached.
+    std::list<int> mUnusedSlots;
+
+    // mActiveBuffers contains all slots which have a non-FREE buffer attached.
+    std::set<int> mActiveBuffers;
 
     // mDequeueCondition is a condition variable used for dequeueBuffer in
     // synchronous mode.
     mutable Condition mDequeueCondition;
 
-    // mUseAsyncBuffer indicates whether an extra buffer is used in async mode
-    // to prevent dequeueBuffer from blocking.
-    bool mUseAsyncBuffer;
-
     // mDequeueBufferCannotBlock indicates whether dequeueBuffer is allowed to
     // block. This flag is set during connect when both the producer and
     // consumer are controlled by the application.
@@ -229,11 +232,9 @@
     // is specified.
     android_dataspace mDefaultBufferDataSpace;
 
-    // mDefaultMaxBufferCount is the default limit on the number of buffers that
-    // will be allocated at one time. This default limit is set by the consumer.
-    // The limit (as opposed to the default limit) may be overriden by the
-    // producer.
-    int mDefaultMaxBufferCount;
+    // mMaxBufferCount is the limit on the number of buffers that will be
+    // allocated at one time. This limit can be set by the consumer.
+    int mMaxBufferCount;
 
     // mMaxAcquiredBufferCount is the number of buffers that the consumer may
     // acquire at one time. It defaults to 1, and can be changed by the consumer
@@ -242,6 +243,11 @@
     // the value returned for the MIN_UNDEQUEUED_BUFFERS query to the producer.
     int mMaxAcquiredBufferCount;
 
+    // mMaxDequeuedBufferCount is the number of buffers that the producer may
+    // dequeue at one time. It defaults to 1, and can be changed by the producer
+    // via setMaxDequeuedBufferCount.
+    int mMaxDequeuedBufferCount;
+
     // mBufferHasBeenQueued is true once a buffer has been queued. It is reset
     // when something causes all buffers to be freed (e.g., changing the buffer
     // count).
@@ -280,6 +286,42 @@
     // number will fail.
     uint32_t mGenerationNumber;
 
+    // mAsyncMode indicates whether or not async mode is enabled.
+    // In async mode an extra buffer will be allocated to allow the producer to
+    // enqueue buffers without blocking.
+    bool mAsyncMode;
+
+    // mSharedBufferMode indicates whether or not shared buffer mode is enabled.
+    bool mSharedBufferMode;
+
+    // When shared buffer mode is enabled, this indicates whether the consumer
+    // should acquire buffers even if BufferQueue doesn't indicate that they are
+    // available.
+    bool mAutoRefresh;
+
+    // When shared buffer mode is enabled, this tracks which slot contains the
+    // shared buffer.
+    int mSharedBufferSlot;
+
+    // Cached data about the shared buffer in shared buffer mode
+    struct SharedBufferCache {
+        SharedBufferCache(Rect _crop, uint32_t _transform, int _scalingMode,
+                android_dataspace _dataspace)
+        : crop(_crop),
+          transform(_transform),
+          scalingMode(_scalingMode),
+          dataspace(_dataspace) {
+        };
+
+        Rect crop;
+        uint32_t transform;
+        uint32_t scalingMode;
+        android_dataspace dataspace;
+    } mSharedBufferCache;
+
+    // The slot of the last queued buffer
+    int mLastQueuedSlot;
+
 }; // class BufferQueueCore
 
 } // namespace android
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 9754a89..a75ed98 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -39,22 +39,11 @@
     // flags indicating that previously-returned buffers are no longer valid.
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
 
-    // setBufferCount updates the number of available buffer slots.  If this
-    // method succeeds, buffer slots will be both unallocated and owned by
-    // the BufferQueue object (i.e. they are not owned by the producer or
-    // consumer).
-    //
-    // This will fail if the producer has dequeued any buffers, or if
-    // bufferCount is invalid.  bufferCount must generally be a value
-    // between the minimum undequeued buffer count (exclusive) and NUM_BUFFER_SLOTS
-    // (inclusive).  It may also be set to zero (the default) to indicate
-    // that the producer does not wish to set a value.  The minimum value
-    // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
-    // ...).
-    //
-    // This may only be called by the producer.  The consumer will be told
-    // to discard buffers through the onBuffersReleased callback.
-    virtual status_t setBufferCount(int bufferCount);
+    // see IGraphicsBufferProducer::setMaxDequeuedBufferCount
+    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+
+    // see IGraphicsBufferProducer::setAsyncMode
+    virtual status_t setAsyncMode(bool async);
 
     // dequeueBuffer gets the next buffer slot index for the producer to use.
     // If a buffer slot is available then that slot index is written to the
@@ -92,7 +81,7 @@
     // In both cases, the producer will need to call requestBuffer to get a
     // GraphicBuffer handle for the returned slot.
     virtual status_t dequeueBuffer(int *outSlot, sp<Fence>* outFence,
-            bool async, uint32_t width, uint32_t height, PixelFormat format,
+            uint32_t width, uint32_t height, PixelFormat format,
             uint32_t usage);
 
     // See IGraphicBufferProducer::detachBuffer
@@ -128,7 +117,7 @@
     //
     // The buffer will not be overwritten until the fence signals.  The fence
     // will usually be the one obtained from dequeueBuffer.
-    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
 
     // Query native window attributes.  The "what" values are enumerated in
     // window.h (e.g. NATIVE_WINDOW_FORMAT).
@@ -169,7 +158,7 @@
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
 
     // See IGraphicBufferProducer::allocateBuffers
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
 
     // See IGraphicBufferProducer::allowAllocation
@@ -181,17 +170,44 @@
     // See IGraphicBufferProducer::getConsumerName
     virtual String8 getConsumerName() const override;
 
+    // See IGraphicBufferProducer::getNextFrameNumber
+    virtual uint64_t getNextFrameNumber() const override;
+
+    // See IGraphicBufferProducer::setSharedBufferMode
+    virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
+
+    // See IGraphicBufferProducer::setAutoRefresh
+    virtual status_t setAutoRefresh(bool autoRefresh) override;
+
+    // See IGraphicBufferProducer::setDequeueTimeout
+    virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+
+    // See IGraphicBufferProducer::getLastQueuedBuffer
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
+
 private:
     // This is required by the IBinder::DeathRecipient interface
     virtual void binderDied(const wp<IBinder>& who);
 
+    // Returns the slot of the next free buffer if one is available or
+    // BufferQueueCore::INVALID_BUFFER_SLOT otherwise
+    int getFreeBufferLocked() const;
+
+    // Returns the next free slot if one is available or
+    // BufferQueueCore::INVALID_BUFFER_SLOT otherwise
+    int getFreeSlotLocked() const;
+
     // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may
     // block if there are no available slots and we are not in non-blocking
     // mode (producer and consumer controlled by the application). If it blocks,
     // it will release mCore->mMutex while blocked so that other operations on
     // the BufferQueue may succeed.
-    status_t waitForFreeSlotThenRelock(const char* caller, bool async,
-            int* found, status_t* returnFlags) const;
+    enum class FreeSlotCaller {
+        Dequeue,
+        Attach,
+    };
+    status_t waitForFreeSlotThenRelock(FreeSlotCaller caller, int* found) const;
 
     sp<BufferQueueCore> mCore;
 
@@ -211,6 +227,9 @@
     // since the previous buffer might have already been acquired.
     sp<Fence> mLastQueueBufferFence;
 
+    Rect mLastQueuedCrop;
+    uint32_t mLastQueuedTransform;
+
     // Take-a-ticket system for ensuring that onFrame* callbacks are called in
     // the order that frames are queued. While the BufferQueue lock
     // (mCore->mMutex) is held, a ticket is retained by the producer. After
@@ -221,6 +240,10 @@
     int mCurrentCallbackTicket; // Protected by mCallbackMutex
     Condition mCallbackCondition;
 
+    // Sets how long dequeueBuffer or attachBuffer will block if a buffer or
+    // slot is not yet available.
+    nsecs_t mDequeueTimeout;
+
 }; // class BufferQueueProducer
 
 } // namespace android
diff --git a/include/gui/BufferSlot.h b/include/gui/BufferSlot.h
index 6085e11..57704b1 100644
--- a/include/gui/BufferSlot.h
+++ b/include/gui/BufferSlot.h
@@ -29,17 +29,160 @@
 
 class Fence;
 
+// BufferState tracks the states in which a buffer slot can be.
+struct BufferState {
+
+    // All slots are initially FREE (not dequeued, queued, acquired, or shared).
+    BufferState()
+    : mDequeueCount(0),
+      mQueueCount(0),
+      mAcquireCount(0),
+      mShared(false) {
+    }
+
+    uint32_t mDequeueCount;
+    uint32_t mQueueCount;
+    uint32_t mAcquireCount;
+    bool mShared;
+
+    // A buffer can be in one of five states, represented as below:
+    //
+    //         | mShared | mDequeueCount | mQueueCount | mAcquireCount |
+    // --------|---------|---------------|-------------|---------------|
+    // FREE    |  false  |       0       |      0      |       0       |
+    // DEQUEUED|  false  |       1       |      0      |       0       |
+    // QUEUED  |  false  |       0       |      1      |       0       |
+    // ACQUIRED|  false  |       0       |      0      |       1       |
+    // SHARED  |  true   |      any      |     any     |      any      |
+    //
+    // FREE indicates that the buffer is available to be dequeued by the
+    // producer. The slot is "owned" by BufferQueue. It transitions to DEQUEUED
+    // when dequeueBuffer is called.
+    //
+    // DEQUEUED indicates that the buffer has been dequeued by the producer, but
+    // has not yet been queued or canceled. The producer may modify the
+    // buffer's contents as soon as the associated release fence is signaled.
+    // The slot is "owned" by the producer. It can transition to QUEUED (via
+    // queueBuffer or attachBuffer) or back to FREE (via cancelBuffer or
+    // detachBuffer).
+    //
+    // QUEUED indicates that the buffer has been filled by the producer and
+    // queued for use by the consumer. The buffer contents may continue to be
+    // modified for a finite time, so the contents must not be accessed until
+    // the associated fence is signaled. The slot is "owned" by BufferQueue. It
+    // can transition to ACQUIRED (via acquireBuffer) or to FREE (if another
+    // buffer is queued in asynchronous mode).
+    //
+    // ACQUIRED indicates that the buffer has been acquired by the consumer. As
+    // with QUEUED, the contents must not be accessed by the consumer until the
+    // acquire fence is signaled. The slot is "owned" by the consumer. It
+    // transitions to FREE when releaseBuffer (or detachBuffer) is called. A
+    // detached buffer can also enter the ACQUIRED state via attachBuffer.
+    //
+    // SHARED indicates that this buffer is being used in shared buffer
+    // mode. It can be in any combination of the other states at the same time,
+    // except for FREE (since that excludes being in any other state). It can
+    // also be dequeued, queued, or acquired multiple times.
+
+    inline bool isFree() const {
+        return !isAcquired() && !isDequeued() && !isQueued();
+    }
+
+    inline bool isDequeued() const {
+        return mDequeueCount > 0;
+    }
+
+    inline bool isQueued() const {
+        return mQueueCount > 0;
+    }
+
+    inline bool isAcquired() const {
+        return mAcquireCount > 0;
+    }
+
+    inline bool isShared() const {
+        return mShared;
+    }
+
+    inline void reset() {
+        *this = BufferState();
+    }
+
+    const char* string() const;
+
+    inline void dequeue() {
+        mDequeueCount++;
+    }
+
+    inline void detachProducer() {
+        if (mDequeueCount > 0) {
+            mDequeueCount--;
+        }
+    }
+
+    inline void attachProducer() {
+        mDequeueCount++;
+    }
+
+    inline void queue() {
+        if (mDequeueCount > 0) {
+            mDequeueCount--;
+        }
+        mQueueCount++;
+    }
+
+    inline void cancel() {
+        if (mDequeueCount > 0) {
+            mDequeueCount--;
+        }
+    }
+
+    inline void freeQueued() {
+        if (mQueueCount > 0) {
+            mQueueCount--;
+        }
+    }
+
+    inline void acquire() {
+        if (mQueueCount > 0) {
+            mQueueCount--;
+        }
+        mAcquireCount++;
+    }
+
+    inline void acquireNotInQueue() {
+        mAcquireCount++;
+    }
+
+    inline void release() {
+        if (mAcquireCount > 0) {
+            mAcquireCount--;
+        }
+    }
+
+    inline void detachConsumer() {
+        if (mAcquireCount > 0) {
+            mAcquireCount--;
+        }
+    }
+
+    inline void attachConsumer() {
+        mAcquireCount++;
+    }
+};
+
 struct BufferSlot {
 
     BufferSlot()
-    : mEglDisplay(EGL_NO_DISPLAY),
-      mBufferState(BufferSlot::FREE),
+    : mGraphicBuffer(nullptr),
+      mEglDisplay(EGL_NO_DISPLAY),
+      mBufferState(),
       mRequestBufferCalled(false),
       mFrameNumber(0),
       mEglFence(EGL_NO_SYNC_KHR),
+      mFence(Fence::NO_FENCE),
       mAcquireCalled(false),
-      mNeedsCleanupOnRelease(false),
-      mAttachedByConsumer(false) {
+      mNeedsReallocation(false) {
     }
 
     // mGraphicBuffer points to the buffer allocated for this slot or is NULL
@@ -49,49 +192,6 @@
     // mEglDisplay is the EGLDisplay used to create EGLSyncKHR objects.
     EGLDisplay mEglDisplay;
 
-    // BufferState represents the different states in which a buffer slot
-    // can be.  All slots are initially FREE.
-    enum BufferState {
-        // FREE indicates that the buffer is available to be dequeued
-        // by the producer.  The buffer may be in use by the consumer for
-        // a finite time, so the buffer must not be modified until the
-        // associated fence is signaled.
-        //
-        // The slot is "owned" by BufferQueue.  It transitions to DEQUEUED
-        // when dequeueBuffer is called.
-        FREE = 0,
-
-        // DEQUEUED indicates that the buffer has been dequeued by the
-        // producer, but has not yet been queued or canceled.  The
-        // producer may modify the buffer's contents as soon as the
-        // associated ready fence is signaled.
-        //
-        // The slot is "owned" by the producer.  It can transition to
-        // QUEUED (via queueBuffer) or back to FREE (via cancelBuffer).
-        DEQUEUED = 1,
-
-        // QUEUED indicates that the buffer has been filled by the
-        // producer and queued for use by the consumer.  The buffer
-        // contents may continue to be modified for a finite time, so
-        // the contents must not be accessed until the associated fence
-        // is signaled.
-        //
-        // The slot is "owned" by BufferQueue.  It can transition to
-        // ACQUIRED (via acquireBuffer) or to FREE (if another buffer is
-        // queued in asynchronous mode).
-        QUEUED = 2,
-
-        // ACQUIRED indicates that the buffer has been acquired by the
-        // consumer.  As with QUEUED, the contents must not be accessed
-        // by the consumer until the fence is signaled.
-        //
-        // The slot is "owned" by the consumer.  It transitions to FREE
-        // when releaseBuffer is called.
-        ACQUIRED = 3
-    };
-
-    static const char* bufferStateName(BufferState state);
-
     // mBufferState is the current state of this buffer slot.
     BufferState mBufferState;
 
@@ -126,15 +226,10 @@
     // Indicates whether this buffer has been seen by a consumer yet
     bool mAcquireCalled;
 
-    // Indicates whether this buffer needs to be cleaned up by the
-    // consumer.  This is set when a buffer in ACQUIRED state is freed.
-    // It causes releaseBuffer to return STALE_BUFFER_SLOT.
-    bool mNeedsCleanupOnRelease;
-
-    // Indicates whether the buffer was attached on the consumer side.
-    // If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when dequeued
-    // to prevent the producer from using a stale cached buffer.
-    bool mAttachedByConsumer;
+    // Indicates whether the buffer was re-allocated without notifying the
+    // producer. If so, it needs to set the BUFFER_NEEDS_REALLOCATION flag when
+    // dequeued to prevent the producer from using a stale cached buffer.
+    bool mNeedsReallocation;
 };
 
 } // namespace android
diff --git a/include/gui/CpuConsumer.h b/include/gui/CpuConsumer.h
index 3b07a31..b7aa463 100644
--- a/include/gui/CpuConsumer.h
+++ b/include/gui/CpuConsumer.h
@@ -67,6 +67,25 @@
         uint8_t    *dataCr;
         uint32_t    chromaStride;
         uint32_t    chromaStep;
+
+        LockedBuffer() :
+            data(NULL),
+            width(0),
+            height(0),
+            format(PIXEL_FORMAT_NONE),
+            stride(0),
+            crop(Rect::EMPTY_RECT),
+            transform(0),
+            scalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+            timestamp(0),
+            dataSpace(HAL_DATASPACE_UNKNOWN),
+            frameNumber(0),
+            flexFormat(PIXEL_FORMAT_NONE),
+            dataCb(NULL),
+            dataCr(NULL),
+            chromaStride(0),
+            chromaStep(0)
+        {}
     };
 
     // Create a new CPU consumer. The maxLockedBuffers parameter specifies
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index c35c7be..6267625 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -110,12 +110,7 @@
     // when the current buffer is released by updateTexImage(). Multiple
     // fences can be set for a given buffer; they will be merged into a single
     // union fence.
-    void setReleaseFence(const sp<Fence>& fence);
-
-    // setDefaultMaxBufferCount sets the default limit on the maximum number
-    // of buffers that will be allocated at one time. The image producer may
-    // override the limit.
-    status_t setDefaultMaxBufferCount(int bufferCount);
+    virtual void setReleaseFence(const sp<Fence>& fence);
 
     // getTransformMatrix retrieves the 4x4 texture coordinate transform matrix
     // associated with the texture image set by the most recent call to
@@ -137,6 +132,12 @@
     // functions.
     void getTransformMatrix(float mtx[16]);
 
+    // Computes the transform matrix documented by getTransformMatrix
+    // from the BufferItem sub parts.
+    static void computeTransformMatrix(float outTransform[16],
+            const sp<GraphicBuffer>& buf, const Rect& cropRect,
+            uint32_t transform, bool filtering);
+
     // getTimestamp retrieves the timestamp associated with the texture image
     // set by the most recent call to updateTexImage.
     //
@@ -201,6 +202,7 @@
     status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace);
     status_t setConsumerUsageBits(uint32_t usage);
     status_t setTransformHint(uint32_t hint);
+    status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers);
 
     // detachFromContext detaches the GLConsumer from the calling thread's
     // current OpenGL ES context.  This context must be the same as the context
@@ -257,10 +259,25 @@
 
     static bool isExternalFormat(PixelFormat format);
 
+    struct PendingRelease {
+        PendingRelease() : isPending(false), currentTexture(-1),
+                graphicBuffer(), display(nullptr), fence(nullptr) {}
+
+        bool isPending;
+        int currentTexture;
+        sp<GraphicBuffer> graphicBuffer;
+        EGLDisplay display;
+        EGLSyncKHR fence;
+    };
+
     // This releases the buffer in the slot referenced by mCurrentTexture,
     // then updates state to refer to the BufferItem, which must be a
-    // newly-acquired buffer.
-    status_t updateAndReleaseLocked(const BufferItem& item);
+    // newly-acquired buffer. If pendingRelease is not null, the parameters
+    // which would have been passed to releaseBufferLocked upon the successful
+    // completion of the method will instead be returned to the caller, so that
+    // it may call releaseBufferLocked itself later.
+    status_t updateAndReleaseLocked(const BufferItem& item,
+            PendingRelease* pendingRelease = nullptr);
 
     // Binds mTexName and the current buffer to mTexTarget.  Uses
     // mCurrentTexture if it's set, mCurrentTextureImage if not.  If the
diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h
index 60ec9cc..e983c16 100644
--- a/include/gui/IGraphicBufferConsumer.h
+++ b/include/gui/IGraphicBufferConsumer.h
@@ -188,35 +188,44 @@
     // * BAD_VALUE - either w or h was zero
     virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
 
-    // setDefaultMaxBufferCount sets the default value for the maximum buffer
-    // count (the initial default is 2). If the producer has requested a
-    // buffer count using setBufferCount, the default buffer count will only
-    // take effect if the producer sets the count back to zero.
+    // setMaxBufferCount sets the maximum value for the number of buffers used
+    // in the buffer queue (the initial default is NUM_BUFFER_SLOTS). If a call
+    // to setMaxAcquiredBufferCount (by the consumer), or a call to setAsyncMode
+    // or setMaxDequeuedBufferCount (by the producer), would cause this value to
+    // be exceeded then that call will fail. This call will fail if a producer
+    // is connected to the BufferQueue.
     //
-    // The count must be between 2 and NUM_BUFFER_SLOTS, inclusive.
+    // The count must be between 1 and NUM_BUFFER_SLOTS, inclusive. The count
+    // cannot be less than maxAcquiredBufferCount.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * BAD_VALUE - bufferCount was out of range (see above).
-    virtual status_t setDefaultMaxBufferCount(int bufferCount) = 0;
-
-    // disableAsyncBuffer disables the extra buffer used in async mode
-    // (when both producer and consumer have set their "isControlledByApp"
-    // flag) and has dequeueBuffer() return WOULD_BLOCK instead.
-    //
-    // This can only be called before consumerConnect().
-    //
-    // Return of a value other than NO_ERROR means an error has occurred:
-    // * INVALID_OPERATION - attempting to call this after consumerConnect.
-    virtual status_t disableAsyncBuffer() = 0;
+    // * BAD_VALUE - one of the below conditions occurred:
+    //             * bufferCount was out of range (see above).
+    //             * failure to adjust the number of available slots.
+    // * INVALID_OPERATION - attempting to call this after a producer connected.
+    virtual status_t setMaxBufferCount(int bufferCount) = 0;
 
     // setMaxAcquiredBufferCount sets the maximum number of buffers that can
-    // be acquired by the consumer at one time (default 1).  This call will
-    // fail if a producer is connected to the BufferQueue.
+    // be acquired by the consumer at one time (default 1). If this method
+    // succeeds, any new buffer slots will be both unallocated and owned by the
+    // BufferQueue object (i.e. they are not owned by the producer or consumer).
+    // Calling this may also cause some buffer slots to be emptied.
     //
-    // maxAcquiredBuffers must be (inclusive) between 1 and MAX_MAX_ACQUIRED_BUFFERS.
+    // This function should not be called with a value of maxAcquiredBuffers
+    // that is less than the number of currently acquired buffer slots. Doing so
+    // will result in a BAD_VALUE error.
+    //
+    // maxAcquiredBuffers must be (inclusive) between 1 and
+    // MAX_MAX_ACQUIRED_BUFFERS. It also cannot cause the maxBufferCount value
+    // to be exceeded.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * BAD_VALUE - maxAcquiredBuffers was out of range (see above).
+    // * NO_INIT - the buffer queue has been abandoned
+    // * BAD_VALUE - one of the below conditions occurred:
+    //             * maxAcquiredBuffers was out of range (see above).
+    //             * failure to adjust the number of available slots.
+    //             * client would have more than the requested number of
+    //               acquired buffers after this call
     // * INVALID_OPERATION - attempting to call this after a producer connected.
     virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
 
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 9530de1..37ae6df 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -74,33 +74,55 @@
     // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - one of the two conditions occurred:
     //              * slot was out of range (see above)
     //              * buffer specified by the slot is not dequeued
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) = 0;
 
-    // setBufferCount sets the number of buffer slots available. Calling this
-    // will also cause all buffer slots to be emptied. The caller should empty
-    // its mirrored copy of the buffer slots when calling this method.
+    // setMaxDequeuedBufferCount sets the maximum number of buffers that can be
+    // dequeued by the producer at one time. If this method succeeds, any new
+    // buffer slots will be both unallocated and owned by the BufferQueue object
+    // (i.e. they are not owned by the producer or consumer). Calling this may
+    // also cause some buffer slots to be emptied. If the caller is caching the
+    // contents of the buffer slots, it should empty that cache after calling
+    // this method.
     //
-    // This function should not be called when there are any dequeued buffer
-    // slots, doing so will result in a BAD_VALUE error returned.
+    // This function should not be called with a value of maxDequeuedBuffers
+    // that is less than the number of currently dequeued buffer slots. Doing so
+    // will result in a BAD_VALUE error.
     //
-    // The buffer count should be at most NUM_BUFFER_SLOTS (inclusive), but at least
-    // the minimum undequeued buffer count (exclusive). The minimum value
-    // can be obtained by calling query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
-    // In particular the range is (minUndequeudBuffers, NUM_BUFFER_SLOTS].
-    //
-    // The buffer count may also be set to 0 (the default), to indicate that
-    // the producer does not wish to set a value.
+    // The buffer count should be at least 1 (inclusive), but at most
+    // (NUM_BUFFER_SLOTS - the minimum undequeued buffer count) (exclusive). The
+    // minimum undequeued buffer count can be obtained by calling
+    // query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
     // * NO_INIT - the buffer queue has been abandoned.
     // * BAD_VALUE - one of the below conditions occurred:
-    //              * bufferCount was out of range (see above)
-    //              * client has one or more buffers dequeued
-    virtual status_t setBufferCount(int bufferCount) = 0;
+    //     * bufferCount was out of range (see above).
+    //     * client would have more than the requested number of dequeued
+    //       buffers after this call.
+    //     * this call would cause the maxBufferCount value to be exceeded.
+    //     * failure to adjust the number of available slots.
+    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) = 0;
+
+    // Set the async flag if the producer intends to asynchronously queue
+    // buffers without blocking. Typically this is used for triple-buffering
+    // and/or when the swap interval is set to zero.
+    //
+    // Enabling async mode will internally allocate an additional buffer to
+    // allow for the asynchronous behavior. If it is not enabled queue/dequeue
+    // calls may block.
+    //
+    // Return of a value other than NO_ERROR means an error has occurred:
+    // * NO_INIT - the buffer queue has been abandoned.
+    // * BAD_VALUE - one of the following has occurred:
+    //             * this call would cause the maxBufferCount value to be
+    //               exceeded
+    //             * failure to adjust the number of available slots.
+    virtual status_t setAsyncMode(bool async) = 0;
 
     // dequeueBuffer requests a new buffer slot for the client to use. Ownership
     // of the slot is transfered to the client, meaning that the server will not
@@ -126,9 +148,6 @@
     // fence signals. If the fence is Fence::NO_FENCE, the buffer may be written
     // immediately.
     //
-    // The async parameter sets whether we're in asynchronous mode for this
-    // dequeueBuffer() call.
-    //
     // The width and height parameters must be no greater than the minimum of
     // GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see: glGetIntegerv).
     // An error due to invalid dimensions might not be reported until
@@ -150,7 +169,8 @@
     // success.
     //
     // Return of a negative means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - both in async mode and buffer count was less than the
     //               max numbers of buffers that can be allocated at once.
     // * INVALID_OPERATION - cannot attach the buffer because it would cause
@@ -162,11 +182,13 @@
     // * WOULD_BLOCK - no buffer is currently available, and blocking is disabled
     //                 since both the producer/consumer are controlled by app
     // * NO_MEMORY - out of memory, cannot allocate the graphics buffer.
+    // * TIMED_OUT - the timeout set by setDequeueTimeout was exceeded while
+    //               waiting for a buffer to become available.
     //
     // All other negative values are an unknown error returned downstream
     // from the graphics allocator (typically errno).
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) = 0;
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t usage) = 0;
 
     // detachBuffer attempts to remove all ownership of the buffer in the given
     // slot from the buffer queue. If this call succeeds, the slot will be
@@ -178,7 +200,8 @@
     // requestBuffer).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - the given slot number is invalid, either because it is
     //               out of the range [0, NUM_BUFFER_SLOTS), or because the slot
     //               it refers to is not currently dequeued and requested.
@@ -198,7 +221,8 @@
     // equivalent to fence from the dequeueBuffer call.
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - either outBuffer or outFence were NULL.
     // * NO_MEMORY - no slots were found that were both free and contained a
     //               GraphicBuffer.
@@ -217,7 +241,8 @@
     // success.
     //
     // Return of a negative value means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - outSlot or buffer were NULL, invalid combination of
     //               async mode and buffer count override, or the generation
     //               number of the buffer did not match the buffer queue.
@@ -230,6 +255,8 @@
     // * WOULD_BLOCK - no buffer slot is currently available, and blocking is
     //                 disabled since both the producer/consumer are
     //                 controlled by the app.
+    // * TIMED_OUT - the timeout set by setDequeueTimeout was exceeded while
+    //               waiting for a slot to become available.
     virtual status_t attachBuffer(int* outSlot,
             const sp<GraphicBuffer>& buffer) = 0;
 
@@ -251,7 +278,8 @@
     // (refer to the documentation below).
     //
     // Return of a value other than NO_ERROR means an error has occurred:
-    // * NO_INIT - the buffer queue has been abandoned.
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
     // * BAD_VALUE - one of the below conditions occurred:
     //              * fence was NULL
     //              * scaling mode was unknown
@@ -271,23 +299,21 @@
         // crop - a crop rectangle that's used as a hint to the consumer
         // scalingMode - a set of flags from NATIVE_WINDOW_SCALING_* in <window.h>
         // transform - a set of flags from NATIVE_WINDOW_TRANSFORM_* in <window.h>
-        // async - if the buffer is queued in asynchronous mode
         // fence - a fence that the consumer must wait on before reading the buffer,
         //         set this to Fence::NO_FENCE if the buffer is ready immediately
         // sticky - the sticky transform set in Surface (only used by the LEGACY
         //          camera mode).
         inline QueueBufferInput(int64_t timestamp, bool isAutoTimestamp,
                 android_dataspace dataSpace, const Rect& crop, int scalingMode,
-                uint32_t transform, bool async, const sp<Fence>& fence,
-                uint32_t sticky = 0)
+                uint32_t transform, const sp<Fence>& fence, uint32_t sticky = 0)
                 : timestamp(timestamp), isAutoTimestamp(isAutoTimestamp),
                   dataSpace(dataSpace), crop(crop), scalingMode(scalingMode),
-                  transform(transform), stickyTransform(sticky),
-                  async(async), fence(fence), surfaceDamage() { }
+                  transform(transform), stickyTransform(sticky), fence(fence),
+                  surfaceDamage() { }
         inline void deflate(int64_t* outTimestamp, bool* outIsAutoTimestamp,
                 android_dataspace* outDataSpace,
                 Rect* outCrop, int* outScalingMode,
-                uint32_t* outTransform, bool* outAsync, sp<Fence>* outFence,
+                uint32_t* outTransform, sp<Fence>* outFence,
                 uint32_t* outStickyTransform = NULL) const {
             *outTimestamp = timestamp;
             *outIsAutoTimestamp = bool(isAutoTimestamp);
@@ -295,7 +321,6 @@
             *outCrop = crop;
             *outScalingMode = scalingMode;
             *outTransform = transform;
-            *outAsync = bool(async);
             *outFence = fence;
             if (outStickyTransform != NULL) {
                 *outStickyTransform = stickyTransform;
@@ -319,7 +344,6 @@
         int scalingMode;
         uint32_t transform;
         uint32_t stickyTransform;
-        int async;
         sp<Fence> fence;
         Region surfaceDamage;
     };
@@ -355,8 +379,8 @@
         uint32_t numPendingBuffers;
     };
 
-    virtual status_t queueBuffer(int slot,
-            const QueueBufferInput& input, QueueBufferOutput* output) = 0;
+    virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
+            QueueBufferOutput* output) = 0;
 
     // cancelBuffer indicates that the client does not wish to fill in the
     // buffer associated with slot and transfers ownership of the slot back to
@@ -364,9 +388,19 @@
     //
     // The buffer is not queued for use by the consumer.
     //
+    // The slot must be in the range of [0, NUM_BUFFER_SLOTS).
+    //
     // The buffer will not be overwritten until the fence signals.  The fence
     // will usually be the one obtained from dequeueBuffer.
-    virtual void cancelBuffer(int slot, const sp<Fence>& fence) = 0;
+    //
+    // Return of a value other than NO_ERROR means an error has occurred:
+    // * NO_INIT - the buffer queue has been abandoned or the producer is not
+    //             connected.
+    // * BAD_VALUE - one of the below conditions occurred:
+    //              * fence was NULL
+    //              * slot index was out of range (see above).
+    //              * the slot was not in the dequeued state
+    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence) = 0;
 
     // query retrieves some information for this surface
     // 'what' tokens allowed are that of NATIVE_WINDOW_* in <window.h>
@@ -407,6 +441,9 @@
     //             * the producer is already connected
     //             * api was out of range (see above).
     //             * output was NULL.
+    //             * Failure to adjust the number of available slots. This can
+    //               happen because of trying to allocate/deallocate the async
+    //               buffer in response to the value of producerControlledByApp.
     // * DEAD_OBJECT - the token is hosted by an already-dead process
     //
     // Additional negative errors may be returned by the internals, they
@@ -457,7 +494,7 @@
     // allocated. This is most useful to avoid an allocation delay during
     // dequeueBuffer. If there are already the maximum number of buffers
     // allocated, this function has no effect.
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage) = 0;
 
     // Sets whether dequeueBuffer is allowed to allocate new buffers.
@@ -483,6 +520,54 @@
 
     // Returns the name of the connected consumer.
     virtual String8 getConsumerName() const = 0;
+
+    // Returns the number of the next frame which will be dequeued.
+    virtual uint64_t getNextFrameNumber() const = 0;
+
+    // Used to enable/disable shared buffer mode.
+    //
+    // When shared buffer mode is enabled the first buffer that is queued or
+    // dequeued will be cached and returned to all subsequent calls to
+    // dequeueBuffer and acquireBuffer. This allows the producer and consumer to
+    // simultaneously access the same buffer.
+    virtual status_t setSharedBufferMode(bool sharedBufferMode) = 0;
+
+    // Used to enable/disable auto-refresh.
+    //
+    // Auto refresh has no effect outside of shared buffer mode. In shared
+    // buffer mode, when enabled, it indicates to the consumer that it should
+    // attempt to acquire buffers even if it is not aware of any being
+    // available.
+    virtual status_t setAutoRefresh(bool autoRefresh) = 0;
+
+    // Sets how long dequeueBuffer will wait for a buffer to become available
+    // before returning an error (TIMED_OUT).
+    //
+    // This timeout also affects the attachBuffer call, which will block if
+    // there is not a free slot available into which the attached buffer can be
+    // placed.
+    //
+    // By default, the BufferQueue will wait forever, which is indicated by a
+    // timeout of -1. If set (to a value other than -1), this will disable
+    // non-blocking mode and its corresponding spare buffer (which is used to
+    // ensure a buffer is always available).
+    //
+    // Return of a value other than NO_ERROR means an error has occurred:
+    // * BAD_VALUE - Failure to adjust the number of available slots. This can
+    //               happen because of trying to allocate/deallocate the async
+    //               buffer.
+    virtual status_t setDequeueTimeout(nsecs_t timeout) = 0;
+
+    // Returns the last queued buffer along with a fence which must signal
+    // before the contents of the buffer are read. If there are no buffers in
+    // the queue, outBuffer will be populated with nullptr and outFence will be
+    // populated with Fence::NO_FENCE
+    //
+    // outTransformMatrix is not modified if outBuffer is null.
+    //
+    // Returns NO_ERROR or the status of the Binder transaction
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/gui/ISensorServer.h b/include/gui/ISensorServer.h
index 3dca2a3..571acb5 100644
--- a/include/gui/ISensorServer.h
+++ b/include/gui/ISensorServer.h
@@ -38,6 +38,8 @@
     DECLARE_META_INTERFACE(SensorServer);
 
     virtual Vector<Sensor> getSensorList(const String16& opPackageName) = 0;
+    virtual Vector<Sensor> getDynamicSensorList(const String16& opPackageName) = 0;
+
     virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
              int mode, const String16& opPackageName) = 0;
     virtual int32_t isDataInjectionEnabled() = 0;
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index 8c3d49e..af26721 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -39,6 +39,7 @@
 class DisplayState;
 struct DisplayInfo;
 struct DisplayStatInfo;
+class HdrCapabilities;
 class IDisplayEventConnection;
 class IMemoryHeap;
 class Rect;
@@ -157,6 +158,13 @@
      * Requires the ACCESS_SURFACE_FLINGER permission.
      */
     virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
+
+    /* Gets the supported HDR capabilities of the given display.
+     *
+     * Requires the ACCESS_SURFACE_FLINGER permission.
+     */
+    virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+            HdrCapabilities* outCapabilities) const = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -184,6 +192,7 @@
         GET_ANIMATION_FRAME_STATS,
         SET_POWER_MODE,
         GET_DISPLAY_STATS,
+        GET_HDR_CAPABILITIES,
     };
 
     virtual status_t onTransact(uint32_t code, const Parcel& data,
diff --git a/include/gui/Sensor.h b/include/gui/Sensor.h
index 8142be6..3f60741 100644
--- a/include/gui/Sensor.h
+++ b/include/gui/Sensor.h
@@ -52,9 +52,19 @@
         TYPE_PROXIMITY      = ASENSOR_TYPE_PROXIMITY
     };
 
-            Sensor();
-            Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
-            ~Sensor();
+    struct uuid_t{
+        union {
+            uint8_t b[16];
+            int64_t i64[2];
+        };
+        uuid_t(const uint8_t (&uuid)[16]) { memcpy(b, uuid, sizeof(b));}
+        uuid_t() : b{0} {}
+    };
+
+    Sensor(const char * name = "");
+    Sensor(struct sensor_t const* hwSensor, int halVersion = 0);
+    Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion = 0);
+    ~Sensor();
 
     const String8& getName() const;
     const String8& getVendor() const;
@@ -76,7 +86,10 @@
     int32_t getMaxDelay() const;
     uint32_t getFlags() const;
     bool isWakeUpSensor() const;
+    bool isDynamicSensor() const;
+    bool hasAdditionalInfo() const;
     int32_t getReportingMode() const;
+    const uuid_t& getUuid() const;
 
     // LightFlattenable protocol
     inline bool isFixedSize() const { return false; }
@@ -103,6 +116,7 @@
     int32_t mRequiredAppOp;
     int32_t mMaxDelay;
     uint32_t mFlags;
+    uuid_t  mUuid;
     static void flattenString8(void*& buffer, size_t& size, const String8& string8);
     static bool unflattenString8(void const*& buffer, size_t& size, String8& outputString8);
 };
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index e5b9fc5..4ee7c02 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -53,6 +53,18 @@
 
     enum { MAX_RECEIVE_BUFFER_EVENT_COUNT = 256 };
 
+    /**
+     * Typical sensor delay (sample period) in microseconds.
+     */
+    // Fastest sampling, system will bound it to minDelay
+    static constexpr int32_t SENSOR_DELAY_FASTEST = 0;
+    // Typical sample period for game, 50Hz;
+    static constexpr int32_t SENSOR_DELAY_GAME = 20000;
+    // Typical sample period for UI, 15Hz
+    static constexpr int32_t SENSOR_DELAY_UI = 66667;
+    // Default sensor sample period
+    static constexpr int32_t SENSOR_DELAY_NORMAL = 200000;
+
     SensorEventQueue(const sp<ISensorEventConnection>& connection);
     virtual ~SensorEventQueue();
     virtual void onFirstRef();
@@ -68,6 +80,7 @@
     status_t wake() const;
 
     status_t enableSensor(Sensor const* sensor) const;
+    status_t enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const;
     status_t disableSensor(Sensor const* sensor) const;
     status_t setEventRate(Sensor const* sensor, nsecs_t ns) const;
 
diff --git a/include/gui/SensorManager.h b/include/gui/SensorManager.h
index 0cff46c..6c6230f 100644
--- a/include/gui/SensorManager.h
+++ b/include/gui/SensorManager.h
@@ -54,7 +54,8 @@
     static SensorManager& getInstanceForPackage(const String16& packageName);
     ~SensorManager();
 
-    ssize_t getSensorList(Sensor const* const** list) const;
+    ssize_t getSensorList(Sensor const* const** list);
+    ssize_t getDynamicSensorList(Vector<Sensor>& list);
     Sensor const* getDefaultSensor(int type);
     sp<SensorEventQueue> createEventQueue(String8 packageName = String8(""), int mode = 0);
     bool isDataInjectionEnabled();
@@ -64,17 +65,17 @@
     void sensorManagerDied();
 
     SensorManager(const String16& opPackageName);
-    status_t assertStateLocked() const;
+    status_t assertStateLocked();
 
 private:
     static Mutex sLock;
     static std::map<String16, SensorManager*> sPackageInstances;
 
-    mutable Mutex mLock;
-    mutable sp<ISensorServer> mSensorServer;
-    mutable Sensor const** mSensorList;
-    mutable Vector<Sensor> mSensors;
-    mutable sp<IBinder::DeathRecipient> mDeathObserver;
+    Mutex mLock;
+    sp<ISensorServer> mSensorServer;
+    Sensor const** mSensorList;
+    Vector<Sensor> mSensors;
+    sp<IBinder::DeathRecipient> mDeathObserver;
     const String16 mOpPackageName;
 };
 
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 72f1067..646203b 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -23,6 +23,8 @@
 #include <ui/ANativeObjectBase.h>
 #include <ui/Region.h>
 
+#include <binder/Parcelable.h>
+
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
@@ -109,6 +111,29 @@
     // See IGraphicBufferProducer::getConsumerName
     String8 getConsumerName() const;
 
+    // See IGraphicBufferProducer::getNextFrameNumber
+    uint64_t getNextFrameNumber() const;
+
+    /* Set the scaling mode to be used with a Surface.
+     * See NATIVE_WINDOW_SET_SCALING_MODE and its parameters
+     * in <system/window.h>. */
+    int setScalingMode(int mode);
+
+    // See IGraphicBufferProducer::setDequeueTimeout
+    status_t setDequeueTimeout(nsecs_t timeout);
+
+    /*
+     * Wait for frame number to increase past lastFrame for at most
+     * timeoutNs. Useful for one thread to wait for another unknown
+     * thread to queue a buffer.
+     */
+    bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
+
+    // See IGraphicBufferProducer::getLastQueuedBuffer
+    // See GLConsumer::getTransformMatrix for outTransformMatrix format
+    status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]);
+
 protected:
     virtual ~Surface();
 
@@ -156,6 +181,8 @@
     int dispatchSetSidebandStream(va_list args);
     int dispatchSetBuffersDataSpace(va_list args);
     int dispatchSetSurfaceDamage(va_list args);
+    int dispatchSetSharedBufferMode(va_list args);
+    int dispatchSetAutoRefresh(va_list args);
 
 protected:
     virtual int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd);
@@ -173,7 +200,6 @@
     virtual int setBuffersDimensions(uint32_t width, uint32_t height);
     virtual int setBuffersUserDimensions(uint32_t width, uint32_t height);
     virtual int setBuffersFormat(PixelFormat format);
-    virtual int setScalingMode(int mode);
     virtual int setBuffersTransform(uint32_t transform);
     virtual int setBuffersStickyTransform(uint32_t transform);
     virtual int setBuffersTimestamp(int64_t timestamp);
@@ -183,6 +209,10 @@
     virtual void setSurfaceDamage(android_native_rect_t* rects, size_t numRects);
 
 public:
+    virtual int setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+    virtual int setAsyncMode(bool async);
+    virtual int setSharedBufferMode(bool sharedBufferMode);
+    virtual int setAutoRefresh(bool autoRefresh);
     virtual int lock(ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds);
     virtual int unlockAndPost();
 
@@ -317,8 +347,60 @@
     // Stores the current generation number. See setGenerationNumber and
     // IGraphicBufferProducer::setGenerationNumber for more information.
     uint32_t mGenerationNumber;
+
+    // Caches the values that have been passed to the producer.
+    bool mSharedBufferMode;
+    bool mAutoRefresh;
+
+    // If in shared buffer mode and auto refresh is enabled, store the shared
+    // buffer slot and return it for all calls to queue/dequeue without going
+    // over Binder.
+    int mSharedBufferSlot;
+
+    // This is true if the shared buffer has already been queued/canceled. It's
+    // used to prevent a mismatch between the number of queue/dequeue calls.
+    bool mSharedBufferHasBeenQueued;
+
+    Condition mQueueBufferCondition;
 };
 
+namespace view {
+
+/**
+ * A simple holder for an IGraphicBufferProducer, to match the managed-side
+ * android.view.Surface parcelable behavior.
+ *
+ * This implements android/view/Surface.aidl
+ *
+ * TODO: Convert IGraphicBufferProducer into AIDL so that it can be directly
+ * used in managed Binder calls.
+ */
+class Surface : public Parcelable {
+  public:
+
+    String16 name;
+    sp<IGraphicBufferProducer> graphicBufferProducer;
+
+    virtual status_t writeToParcel(Parcel* parcel) const override;
+    virtual status_t readFromParcel(const Parcel* parcel) override;
+
+    // nameAlreadyWritten set to true by Surface.java, because it splits
+    // Parceling itself between managed and native code, so it only wants a part
+    // of the full parceling to happen on its native side.
+    status_t writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const;
+
+    // nameAlreadyRead set to true by Surface.java, because it splits
+    // Parceling itself between managed and native code, so it only wants a part
+    // of the full parceling to happen on its native side.
+    status_t readFromParcel(const Parcel* parcel, bool nameAlreadyRead);
+
+  private:
+
+    static String16 readMaybeEmptyString16(const Parcel* parcel);
+};
+
+} // namespace view
+
 }; // namespace android
 
 #endif  // ANDROID_GUI_SURFACE_H
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h
index 37d953e..73f923c 100644
--- a/include/gui/SurfaceComposerClient.h
+++ b/include/gui/SurfaceComposerClient.h
@@ -40,6 +40,7 @@
 
 class DisplayInfo;
 class Composer;
+class HdrCapabilities;
 class ISurfaceComposerClient;
 class IGraphicBufferProducer;
 class Region;
@@ -133,7 +134,12 @@
     status_t    setPosition(const sp<IBinder>& id, float x, float y);
     status_t    setSize(const sp<IBinder>& id, uint32_t w, uint32_t h);
     status_t    setCrop(const sp<IBinder>& id, const Rect& crop);
+    status_t    setFinalCrop(const sp<IBinder>& id, const Rect& crop);
     status_t    setLayerStack(const sp<IBinder>& id, uint32_t layerStack);
+    status_t    deferTransactionUntil(const sp<IBinder>& id,
+            const sp<IBinder>& handle, uint64_t frameNumber);
+    status_t    setOverrideScalingMode(const sp<IBinder>& id,
+            int32_t overrideScalingMode);
     status_t    destroySurface(const sp<IBinder>& id);
 
     status_t clearLayerFrameStats(const sp<IBinder>& token) const;
@@ -142,6 +148,9 @@
     static status_t clearAnimationFrameStats();
     static status_t getAnimationFrameStats(FrameStats* outStats);
 
+    static status_t getHdrCapabilities(const sp<IBinder>& display,
+            HdrCapabilities* outCapabilities);
+
     static void setDisplaySurface(const sp<IBinder>& token,
             const sp<IGraphicBufferProducer>& bufferProducer);
     static void setDisplayLayerStack(const sp<IBinder>& token,
diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h
index 9f62f7c..bedebb6 100644
--- a/include/gui/SurfaceControl.h
+++ b/include/gui/SurfaceControl.h
@@ -57,6 +57,9 @@
     // release surface data from java
     void        clear();
 
+    // disconnect any api that's connected
+    void        disconnect();
+
     status_t    setLayerStack(uint32_t layerStack);
     status_t    setLayer(uint32_t layer);
     status_t    setPosition(float x, float y);
@@ -68,11 +71,22 @@
     status_t    setAlpha(float alpha=1.0f);
     status_t    setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
     status_t    setCrop(const Rect& crop);
+    status_t    setFinalCrop(const Rect& crop);
+
+    // Defers applying any changes made in this transaction until the Layer
+    // identified by handle reaches the given frameNumber
+    status_t deferTransactionUntil(sp<IBinder> handle, uint64_t frameNumber);
+
+    // Set an override scaling mode as documented in <system/window.h>
+    // the override scaling mode will take precedence over any client
+    // specified scaling mode. -1 will clear the override scaling mode.
+    status_t setOverrideScalingMode(int32_t overrideScalingMode);
 
     static status_t writeSurfaceToParcel(
             const sp<SurfaceControl>& control, Parcel* parcel);
 
     sp<Surface> getSurface() const;
+    sp<IBinder> getHandle() const;
 
     status_t clearLayerFrameStats() const;
     status_t getLayerFrameStats(FrameStats* outStats) const;
diff --git a/include/input/Input.h b/include/input/Input.h
index 82fc659..55787e7 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -153,7 +153,7 @@
 
 namespace android {
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
 class Parcel;
 #endif
 
@@ -248,7 +248,7 @@
         return getAxisValue(AMOTION_EVENT_AXIS_Y);
     }
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
     status_t readFromParcel(Parcel* parcel);
     status_t writeToParcel(Parcel* parcel) const;
 #endif
@@ -586,7 +586,7 @@
     // Matrix is in row-major form and compatible with SkMatrix.
     void transform(const float matrix[9]);
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
     status_t readFromParcel(Parcel* parcel);
     status_t writeToParcel(Parcel* parcel) const;
 #endif
diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h
index f0a6238..b7012eb 100644
--- a/include/input/InputEventLabels.h
+++ b/include/input/InputEventLabels.h
@@ -307,11 +307,18 @@
     DEFINE_KEYCODE(STEM_1),
     DEFINE_KEYCODE(STEM_2),
     DEFINE_KEYCODE(STEM_3),
+    DEFINE_KEYCODE(DPAD_UP_LEFT),
+    DEFINE_KEYCODE(DPAD_DOWN_LEFT),
+    DEFINE_KEYCODE(DPAD_UP_RIGHT),
+    DEFINE_KEYCODE(DPAD_DOWN_RIGHT),
     DEFINE_KEYCODE(MEDIA_SKIP_FORWARD),
     DEFINE_KEYCODE(MEDIA_SKIP_BACKWARD),
     DEFINE_KEYCODE(MEDIA_STEP_FORWARD),
     DEFINE_KEYCODE(MEDIA_STEP_BACKWARD),
     DEFINE_KEYCODE(SOFT_SLEEP),
+    DEFINE_KEYCODE(CUT),
+    DEFINE_KEYCODE(COPY),
+    DEFINE_KEYCODE(PASTE),
 
     { NULL, 0 }
 };
diff --git a/include/input/KeyCharacterMap.h b/include/input/KeyCharacterMap.h
index 3f0914b..7935927 100644
--- a/include/input/KeyCharacterMap.h
+++ b/include/input/KeyCharacterMap.h
@@ -19,7 +19,7 @@
 
 #include <stdint.h>
 
-#if HAVE_ANDROID_OS
+#ifdef __ANDROID__
 #include <binder/IBinder.h>
 #endif
 
@@ -31,6 +31,9 @@
 #include <utils/Unicode.h>
 #include <utils/RefBase.h>
 
+// Maximum number of keys supported by KeyCharacterMaps
+#define MAX_KEYS 8192
+
 namespace android {
 
 /**
@@ -129,7 +132,7 @@
     void tryRemapKey(int32_t scanCode, int32_t metaState,
             int32_t* outKeyCode, int32_t* outMetaState) const;
 
-#if HAVE_ANDROID_OS
+#ifdef __ANDROID__
     /* Reads a key map from a parcel. */
     static sp<KeyCharacterMap> readFromParcel(Parcel* parcel);
 
diff --git a/include/media/drm/DrmAPI.h b/include/media/drm/DrmAPI.h
index 272881b..985d919 100644
--- a/include/media/drm/DrmAPI.h
+++ b/include/media/drm/DrmAPI.h
@@ -220,9 +220,6 @@
                                                   Vector<uint8_t> &certificate,
                                                   Vector<uint8_t> &wrapped_key) = 0;
 
-        // Remove device provisioning.
-        virtual status_t unprovisionDevice() = 0;
-
         // A means of enforcing the contractual requirement for a concurrent stream
         // limit per subscriber across devices is provided via SecureStop.  SecureStop
         // is a means of securely monitoring the lifetime of sessions. Since playback
diff --git a/include/media/hardware/CryptoAPI.h b/include/media/hardware/CryptoAPI.h
index 3e3257f..0e86aac 100644
--- a/include/media/hardware/CryptoAPI.h
+++ b/include/media/hardware/CryptoAPI.h
@@ -46,10 +46,8 @@
     enum Mode {
         kMode_Unencrypted = 0,
         kMode_AES_CTR     = 1,
-
-        // Neither key nor iv are being used in this mode.
-        // Each subsample is encrypted w/ an iv of all zeroes.
-        kMode_AES_WV      = 2,  // FIX constant
+        kMode_AES_WV      = 2,
+        kMode_AES_CBC     = 3,
     };
 
     struct SubSample {
@@ -57,6 +55,16 @@
         uint32_t mNumBytesOfEncryptedData;
     };
 
+    struct Pattern {
+        // Number of blocks to be encrypted in the pattern. If zero, pattern
+        // encryption is inoperative.
+        uint32_t mEncryptBlocks;
+
+        // Number of blocks to be skipped (left clear) in the pattern. If zero,
+        // pattern encryption is inoperative.
+        uint32_t mSkipBlocks;
+    };
+
     CryptoPlugin() {}
     virtual ~CryptoPlugin() {}
 
@@ -96,6 +104,7 @@
             const uint8_t key[16],
             const uint8_t iv[16],
             Mode mode,
+            const Pattern &pattern,
             const void *srcPtr,
             const SubSample *subSamples, size_t numSubSamples,
             void *dstPtr,
diff --git a/include/media/hardware/HardwareAPI.h b/include/media/hardware/HardwareAPI.h
index 1008c22..2c50ad6 100644
--- a/include/media/hardware/HardwareAPI.h
+++ b/include/media/hardware/HardwareAPI.h
@@ -23,10 +23,17 @@
 #include <system/window.h>
 #include <utils/RefBase.h>
 
+#include "VideoAPI.h"
+
 #include <OMX_Component.h>
 
 namespace android {
 
+// This structure is used to enable Android native buffer use for either
+// graphic buffers or secure buffers.
+//
+// TO CONTROL ANDROID GRAPHIC BUFFER USAGE:
+//
 // A pointer to this struct is passed to the OMX_SetParameter when the extension
 // index for the 'OMX.google.android.index.enableAndroidNativeBuffers' extension
 // is given.
@@ -45,6 +52,25 @@
 // 'OMX.google.android.index.useAndroidNativeBuffer2' extension, it should
 // expect to receive UseAndroidNativeBuffer calls (via OMX_SetParameter) rather
 // than UseBuffer calls for that port.
+//
+// TO CONTROL ANDROID SECURE BUFFER USAGE:
+//
+// A pointer to this struct is passed to the OMX_SetParameter when the extension
+// index for the 'OMX.google.android.index.allocateNativeHandle' extension
+// is given.
+//
+// When native handle use is disabled for a port (the default state),
+// the OMX node should operate as normal, and expect AllocateBuffer calls to
+// return buffer pointers. This is the mode that will be used for non-secure
+// buffers if component requires allocate buffers instead of use buffers.
+//
+// When native handle use has been enabled for a given port, the component
+// shall allocate native_buffer_t objects containing  that can be passed between
+// processes using binder. This is the mode that will be used for secure buffers.
+// When an OMX component allocates native handle for buffers, it must close and
+// delete that handle when it frees those buffers. Even though pBuffer will point
+// to a native handle, nFilledLength, nAllocLength and nOffset will correspond
+// to the data inside the opaque buffer.
 struct EnableAndroidNativeBuffersParams {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -52,6 +78,8 @@
     OMX_BOOL enable;
 };
 
+typedef struct EnableAndroidNativeBuffersParams AllocateNativeHandleParams;
+
 // A pointer to this struct is passed to OMX_SetParameter() when the extension index
 // "OMX.google.android.index.storeMetaDataInBuffers" or
 // "OMX.google.android.index.storeANWBufferInMetadata" is given.
@@ -120,6 +148,17 @@
     int nFenceFd;                           // -1 if unused
 };
 
+// Meta data buffer layout for passing a native_handle to codec
+struct VideoNativeHandleMetadata {
+    MetadataBufferType eType;               // must be kMetadataBufferTypeNativeHandleSource
+
+#ifdef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+    OMX_PTR pHandle;
+#else
+    native_handle_t *pHandle;
+#endif
+};
+
 // A pointer to this struct is passed to OMX_SetParameter() when the extension
 // index "OMX.google.android.index.prepareForAdaptivePlayback" is given.
 //
@@ -188,37 +227,6 @@
     OMX_BOOL bEnable;
 };
 
-// Structure describing a media image (frame)
-// Currently only supporting YUV
-struct MediaImage {
-    enum Type {
-        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
-        MEDIA_IMAGE_TYPE_YUV,
-    };
-
-    enum PlaneIndex {
-        Y = 0,
-        U,
-        V,
-        MAX_NUM_PLANES
-    };
-
-    Type mType;
-    uint32_t mNumPlanes;              // number of planes
-    uint32_t mWidth;                  // width of largest plane (unpadded, as in nFrameWidth)
-    uint32_t mHeight;                 // height of largest plane (unpadded, as in nFrameHeight)
-    uint32_t mBitDepth;               // useable bit depth
-    struct PlaneInfo {
-        uint32_t mOffset;             // offset of first pixel of the plane in bytes
-                                      // from buffer offset
-        uint32_t mColInc;             // column increment in bytes
-        uint32_t mRowInc;             // row increment in bytes
-        uint32_t mHorizSubsampling;   // subsampling compared to the largest plane
-        uint32_t mVertSubsampling;    // subsampling compared to the largest plane
-    };
-    PlaneInfo mPlane[MAX_NUM_PLANES];
-};
-
 // A pointer to this struct is passed to OMX_GetParameter when the extension
 // index for the 'OMX.google.android.index.describeColorFormat'
 // extension is given.  This method can be called from any component state
@@ -245,6 +253,9 @@
 // For non-YUV packed planar/semiplanar image formats, or if bUsingNativeBuffers
 // is OMX_TRUE and the component does not support this color format with native
 // buffers, the component shall set mNumPlanes to 0, and mType to MEDIA_IMAGE_TYPE_UNKNOWN.
+
+// @deprecated: use DescribeColorFormat2Params
+struct DescribeColorFormat2Params;
 struct DescribeColorFormatParams {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
@@ -258,6 +269,29 @@
 
     // output: fill out the MediaImage fields
     MediaImage sMediaImage;
+
+    DescribeColorFormatParams(const DescribeColorFormat2Params&); // for internal use only
+};
+
+// A pointer to this struct is passed to OMX_GetParameter when the extension
+// index for the 'OMX.google.android.index.describeColorFormat2'
+// extension is given. This is operationally the same as DescribeColorFormatParams
+// but can be used for HDR and RGBA/YUVA formats.
+struct DescribeColorFormat2Params {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    // input: parameters from OMX_VIDEO_PORTDEFINITIONTYPE
+    OMX_COLOR_FORMATTYPE eColorFormat;
+    OMX_U32 nFrameWidth;
+    OMX_U32 nFrameHeight;
+    OMX_U32 nStride;
+    OMX_U32 nSliceHeight;
+    OMX_BOOL bUsingNativeBuffers;
+
+    // output: fill out the MediaImage2 fields
+    MediaImage2 sMediaImage;
+
+    void initFromV1(const DescribeColorFormatParams&); // for internal use only
 };
 
 // A pointer to this struct is passed to OMX_SetParameter or OMX_GetParameter
@@ -281,6 +315,185 @@
     OMX_PTR pSidebandWindow;    // OUT
 };
 
+// Color space description (aspects) parameters.
+// This is passed via OMX_SetConfig or OMX_GetConfig to video encoders and decoders when the
+// 'OMX.google.android.index.describeColorAspects' extension is given. Component SHALL behave
+// as described below if it supports this extension.
+//
+// bDataSpaceChanged and bRequestingDataSpace is assumed to be OMX_FALSE unless noted otherwise.
+//
+// VIDEO ENCODERS: the framework uses OMX_SetConfig to specify color aspects of the coded video.
+// This may happen:
+//   a) before the component transitions to idle state
+//   b) before the input frame is sent via OMX_EmptyThisBuffer in executing state
+//   c) during execution, just before an input frame with a different color aspect information
+//      is sent.
+//
+// The framework also uses OMX_GetConfig to
+//   d) verify the color aspects that will be written to the stream
+//   e) (optional) verify the color aspects that should be reported to the container for a
+//      given dataspace/pixelformat received
+//
+// 1. Encoders SHOULD maintain an internal color aspect state, initialized to Unspecified values.
+//    This represents the values that will be written into the bitstream.
+// 2. Upon OMX_SetConfig, they SHOULD update their internal state to the aspects received
+//    (including Unspecified values). For specific aspect values that are not supported by the
+//    codec standard, encoders SHOULD substitute Unspecified values; or they MAY use a suitable
+//    alternative (e.g. to suggest the use of BT.709 EOTF instead of SMPTE 240M.)
+// 3. OMX_GetConfig SHALL return the internal state (values that will be written).
+// 4. OMX_SetConfig SHALL always succeed before receiving the first frame. It MAY fail afterwards,
+//    but only if the configured values would change AND the component does not support updating the
+//    color information to those values mid-stream. If component supports updating a portion of
+//    the color information, those values should be updated in the internal state, and OMX_SetConfig
+//    SHALL succeed. Otherwise, the internal state SHALL remain intact and OMX_SetConfig SHALL fail
+//    with OMX_ErrorUnsupportedSettings.
+// 5. When the framework receives an input frame with an unexpected dataspace, it will query
+//    encoders for the color aspects that should be reported to the container using OMX_GetConfig
+//    with bDataSpaceChanged set to OMX_TRUE, and nPixelFormat/nDataSpace containing the new
+//    format/dataspace values. This allows vendors to use extended dataspace during capture and
+//    composition (e.g. screenrecord) - while performing color-space conversion inside the encoder -
+//    and encode and report a different color-space information in the bitstream/container.
+//    sColorAspects contains the requested color aspects by the client for reference, which may
+//    include aspects not supported by the encoding. This is used together with guidance for
+//    dataspace selection; see 6. below.
+//
+// VIDEO DECODERS: the framework uses OMX_SetConfig to specify the default color aspects to use
+// for the video.
+// This may happen:
+//   a) before the component transitions to idle state
+//   b) during execution, when the resolution or the default color aspects change.
+//
+// The framework also uses OMX_GetConfig to
+//   c) get the final color aspects reported by the coded bitstream after taking the default values
+//      into account.
+//
+// 1. Decoders should maintain two color aspect states - the default state as reported by the
+//    framework, and the coded state as reported by the bitstream - as each state can change
+//    independently from the other.
+// 2. Upon OMX_SetConfig, it SHALL update its default state regardless of whether such aspects
+//    could be supplied by the component bitstream. (E.g. it should blindly support all enumeration
+//    values, even unknown ones, and the Other value). This SHALL always succeed.
+// 3. Upon OMX_GetConfig, the component SHALL return the final color aspects by replacing
+//    Unspecified coded values with the default values. This SHALL always succeed.
+// 4. Whenever the component processes color aspect information in the bitstream even with an
+//    Unspecified value, it SHOULD update its internal coded state with that information just before
+//    the frame with the new information would be outputted, and the component SHALL signal an
+//    OMX_EventPortSettingsChanged event with data2 set to the extension index.
+// NOTE: Component SHOULD NOT signal a separate event purely for color aspect change, if it occurs
+//    together with a port definition (e.g. size) or crop change.
+// 5. If the aspects a component encounters in the bitstream cannot be represented with enumeration
+//    values as defined below, the component SHALL set those aspects to Other. Restricted values in
+//    the bitstream SHALL be treated as defined by the relevant bitstream specifications/standards,
+//    or as Unspecified, if not defined.
+//
+// BOTH DECODERS AND ENCODERS: the framework uses OMX_GetConfig during idle and executing state to
+//   f) (optional) get guidance for the dataspace to set for given color aspects, by setting
+//      bRequestingDataSpace to OMX_TRUE. The component SHALL return OMX_ErrorUnsupportedSettings
+//      IF it does not support this request.
+//
+// 6. This is an information request that can happen at any time, independent of the normal
+//    configuration process. This allows vendors to use extended dataspace during capture, playback
+//    and composition - while performing color-space conversion inside the component. Component
+//    SHALL set the desired dataspace into nDataSpace. Otherwise, it SHALL return
+//    OMX_ErrorUnsupportedSettings to let the framework choose a nearby standard dataspace.
+//
+// 6.a. For encoders, this query happens before the first frame is received using surface encoding.
+//    This allows the encoder to use a specific dataspace for the color aspects (e.g. because the
+//    device supports additional dataspaces, or because it wants to perform color-space extension
+//    to facilitate a more optimal rendering/capture pipeline.).
+//
+// 6.b. For decoders, this query happens before the first frame, and every time the color aspects
+//    change, while using surface buffers. This allows the decoder to use a specific dataspace for
+//    the color aspects (e.g. because the device supports additional dataspaces, or because it wants
+//    to perform color-space extension by inline color-space conversion to facilitate a more optimal
+//    rendering pipeline.).
+//
+// Note: the size of sAspects may increase in the future by additional fields.
+// Implementations SHOULD NOT require a certain size.
+struct DescribeColorAspectsParams {
+    OMX_U32 nSize;                 // IN
+    OMX_VERSIONTYPE nVersion;      // IN
+    OMX_U32 nPortIndex;            // IN
+    OMX_BOOL bRequestingDataSpace; // IN
+    OMX_BOOL bDataSpaceChanged;    // IN
+    OMX_U32 nPixelFormat;          // IN
+    OMX_U32 nDataSpace;            // OUT
+    ColorAspects sAspects;         // IN/OUT
+};
+
+// HDR color description parameters.
+// This is passed via OMX_SetConfig or OMX_GetConfig to video encoders and decoders when the
+// 'OMX.google.android.index.describeHDRColorInfo' extension is given and an HDR stream
+// is detected.  Component SHALL behave as described below if it supports this extension.
+//
+// Currently, only Static Metadata Descriptor Type 1 support is required.
+//
+// VIDEO ENCODERS: the framework uses OMX_SetConfig to specify the HDR static information of the
+// coded video.
+// This may happen:
+//   a) before the component transitions to idle state
+//   b) before the input frame is sent via OMX_EmptyThisBuffer in executing state
+//   c) during execution, just before an input frame with a different HDR static
+//      information is sent.
+//
+// The framework also uses OMX_GetConfig to
+//   d) verify the HDR static information that will be written to the stream.
+//
+// 1. Encoders SHOULD maintain an internal HDR static info data, initialized to Unspecified values.
+//    This represents the values that will be written into the bitstream.
+// 2. Upon OMX_SetConfig, they SHOULD update their internal state to the info received
+//    (including Unspecified values). For specific parameters that are not supported by the
+//    codec standard, encoders SHOULD substitute Unspecified values. NOTE: no other substitution
+//    is allowed.
+// 3. OMX_GetConfig SHALL return the internal state (values that will be written).
+// 4. OMX_SetConfig SHALL always succeed before receiving the first frame if the encoder is
+//    configured into an HDR compatible profile. It MAY fail with OMX_ErrorUnsupportedSettings error
+//    code if it is not configured into such a profile, OR if the configured values would change
+//    AND the component does not support updating the HDR static information mid-stream. If the
+//    component supports updating a portion of the information, those values should be updated in
+//    the internal state, and OMX_SetConfig SHALL succeed. Otherwise, the internal state SHALL
+//    remain intact.
+//
+// VIDEO DECODERS: the framework uses OMX_SetConfig to specify the default HDR static information
+// to use for the video.
+//   a) This only happens if the client supplies this information, in which case it occurs before
+//      the component transitions to idle state.
+//   b) This may also happen subsequently if the default HDR static information changes.
+//
+// The framework also uses OMX_GetConfig to
+//   c) get the final HDR static information reported by the coded bitstream after taking the
+//      default values into account.
+//
+// 1. Decoders should maintain two HDR static information structures - the default values as
+//    reported by the framework, and the coded values as reported by the bitstream - as each
+//    structure can change independently from the other.
+// 2. Upon OMX_SetConfig, it SHALL update its default structure regardless of whether such static
+//    parameters could be supplied by the component bitstream. (E.g. it should blindly support all
+//    parameter values, even seemingly illegal ones). This SHALL always succeed.
+//  Note: The descriptor ID used in sInfo may change in subsequent calls. (although for now only
+//    Type 1 support is required.)
+// 3. Upon OMX_GetConfig, the component SHALL return the final HDR static information by replacing
+//    Unspecified coded values with the default values. This SHALL always succeed. This may be
+//    provided using any supported descriptor ID (currently only Type 1) with the goal of expressing
+//    the most of the available static information.
+// 4. Whenever the component processes HDR static information in the bitstream even ones with
+//    Unspecified parameters, it SHOULD update its internal coded structure with that information
+//    just before the frame with the new information would be outputted, and the component SHALL
+//    signal an OMX_EventPortSettingsChanged event with data2 set to the extension index.
+// NOTE: Component SHOULD NOT signal a separate event purely for HDR static info change, if it
+//    occurs together with a port definition (e.g. size), color aspect or crop change.
+// 5. If certain parameters of the HDR static information encountered in the bitstream cannot be
+//    represented using sInfo, the component SHALL use the closest representation.
+//
+// Note: the size of sInfo may increase in the future by supporting additional descriptor types.
+// Implementations SHOULD NOT require a certain size.
+struct DescribeHDRStaticInfoParams {
+    OMX_U32 nSize;                 // IN
+    OMX_VERSIONTYPE nVersion;      // IN
+    OMX_U32 nPortIndex;            // IN
+    HDRStaticInfo sInfo;           // IN/OUT
+};
+
 }  // namespace android
 
 extern android::OMXPluginBase *createOMXPlugin();
diff --git a/include/media/hardware/MetadataBufferType.h b/include/media/hardware/MetadataBufferType.h
index b765203..4f6d5e2 100644
--- a/include/media/hardware/MetadataBufferType.h
+++ b/include/media/hardware/MetadataBufferType.h
@@ -111,6 +111,28 @@
      */
     kMetadataBufferTypeANWBuffer = 2,
 
+    /*
+     * kMetadataBufferTypeNativeHandleSource is used to indicate that
+     * the payload of the metadata buffers can be interpreted as
+     * a native_handle_t.
+     *
+     * In this case, the metadata that the encoder receives
+     * will have a byte stream that consists of two parts:
+     * 1. First, there is an integer indicating that the metadata contains a
+     * native handle (kMetadataBufferTypeNativeHandleSource).
+     * 2. This is followed by a pointer to native_handle_t. The encoder needs
+     * to interpret this native handle and encode the frame. The encoder must
+     * not free this native handle as it does not actually own this native
+     * handle. The handle will be freed after the encoder releases the buffer
+     * back to camera.
+     * ----------------------------------------------------------------
+     * |  kMetadataBufferTypeNativeHandleSource | native_handle_t* nh |
+     * ----------------------------------------------------------------
+     *
+     * See the VideoNativeHandleMetadata structure.
+     */
+    kMetadataBufferTypeNativeHandleSource = 3,
+
     /* This value is used by framework, but is never used inside a metadata buffer  */
     kMetadataBufferTypeInvalid = -1,
 
diff --git a/include/media/hardware/VideoAPI.h b/include/media/hardware/VideoAPI.h
new file mode 100644
index 0000000..3667c4b
--- /dev/null
+++ b/include/media/hardware/VideoAPI.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef VIDEO_API_H_
+
+#define VIDEO_API_H_
+
+namespace android {
+
+/**
+ * Structure describing a media image (frame)
+ * Currently only supporting YUV
+ * @deprecated. Use MediaImage2 instead
+ */
+struct MediaImage {
+    enum Type {
+        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
+        MEDIA_IMAGE_TYPE_YUV,
+    };
+
+    enum PlaneIndex {
+        Y = 0,
+        U,
+        V,
+        MAX_NUM_PLANES
+    };
+
+    Type mType;
+    uint32_t mNumPlanes;              // number of planes
+    uint32_t mWidth;                  // width of largest plane (unpadded, as in nFrameWidth)
+    uint32_t mHeight;                 // height of largest plane (unpadded, as in nFrameHeight)
+    uint32_t mBitDepth;               // useable bit depth
+    struct PlaneInfo {
+        uint32_t mOffset;             // offset of first pixel of the plane in bytes
+                                      // from buffer offset
+        uint32_t mColInc;             // column increment in bytes
+        uint32_t mRowInc;             // row increment in bytes
+        uint32_t mHorizSubsampling;   // subsampling compared to the largest plane
+        uint32_t mVertSubsampling;    // subsampling compared to the largest plane
+    };
+    PlaneInfo mPlane[MAX_NUM_PLANES];
+};
+
+/**
+ * Structure describing a media image (frame)
+ */
+struct __attribute__ ((__packed__)) MediaImage2 {
+    enum Type : uint32_t {
+        MEDIA_IMAGE_TYPE_UNKNOWN = 0,
+        MEDIA_IMAGE_TYPE_YUV,
+        MEDIA_IMAGE_TYPE_YUVA,
+        MEDIA_IMAGE_TYPE_RGB,
+        MEDIA_IMAGE_TYPE_RGBA,
+        MEDIA_IMAGE_TYPE_Y,
+    };
+
+    enum PlaneIndex : uint32_t {
+        Y = 0,
+        U = 1,
+        V = 2,
+        R = 0,
+        G = 1,
+        B = 2,
+        A = 3,
+        MAX_NUM_PLANES = 4,
+    };
+
+    Type mType;
+    uint32_t mNumPlanes;              // number of planes
+    uint32_t mWidth;                  // width of largest plane (unpadded, as in nFrameWidth)
+    uint32_t mHeight;                 // height of largest plane (unpadded, as in nFrameHeight)
+    uint32_t mBitDepth;               // useable bit depth (always MSB)
+    uint32_t mBitDepthAllocated;      // bits per component (must be 8 or 16)
+
+    struct __attribute__ ((__packed__)) PlaneInfo {
+        uint32_t mOffset;             // offset of first pixel of the plane in bytes
+                                      // from buffer offset
+        int32_t mColInc;              // column increment in bytes
+        int32_t mRowInc;              // row increment in bytes
+        uint32_t mHorizSubsampling;   // subsampling compared to the largest plane
+        uint32_t mVertSubsampling;    // subsampling compared to the largest plane
+    };
+    PlaneInfo mPlane[MAX_NUM_PLANES];
+
+    void initFromV1(const MediaImage&); // for internal use only
+};
+
+static_assert(sizeof(MediaImage2::PlaneInfo) == 20, "wrong struct size");
+static_assert(sizeof(MediaImage2) == 104, "wrong struct size");
+
+/**
+ * Aspects of color.
+ */
+
+// NOTE: this structure is expected to grow in the future if new color aspects are
+// added to codec bitstreams. OMX component should not require a specific nSize
+// though could verify that nSize is at least the size of the structure at the
+// time of implementation. All new fields will be added at the end of the structure
+// ensuring backward compatibility.
+struct __attribute__ ((__packed__)) ColorAspects {
+    // this is in sync with the range values in graphics.h
+    enum Range : uint32_t {
+        RangeUnspecified,
+        RangeFull,
+        RangeLimited,
+        RangeOther = 0xff,
+    };
+
+    enum Primaries : uint32_t {
+        PrimariesUnspecified,
+        PrimariesBT709_5,       // Rec.ITU-R BT.709-5 or equivalent
+        PrimariesBT470_6M,      // Rec.ITU-R BT.470-6 System M or equivalent
+        PrimariesBT601_6_625,   // Rec.ITU-R BT.601-6 625 or equivalent
+        PrimariesBT601_6_525,   // Rec.ITU-R BT.601-6 525 or equivalent
+        PrimariesGenericFilm,   // Generic Film
+        PrimariesBT2020,        // Rec.ITU-R BT.2020 or equivalent
+        PrimariesOther = 0xff,
+    };
+
+    // this partially in sync with the transfer values in graphics.h prior to the transfers
+    // unlikely to be required by Android section
+    enum Transfer : uint32_t {
+        TransferUnspecified,
+        TransferLinear,         // Linear transfer characteristics
+        TransferSRGB,           // sRGB or equivalent
+        TransferSMPTE170M,      // SMPTE 170M or equivalent (e.g. BT.601/709/2020)
+        TransferGamma22,        // Assumed display gamma 2.2
+        TransferGamma28,        // Assumed display gamma 2.8
+        TransferST2084,         // SMPTE ST 2084 for 10/12/14/16 bit systems
+        TransferHLG,            // ARIB STD-B67 hybrid-log-gamma
+
+        // transfers unlikely to be required by Android
+        TransferSMPTE240M = 0x40, // SMPTE 240M
+        TransferXvYCC,          // IEC 61966-2-4
+        TransferBT1361,         // Rec.ITU-R BT.1361 extended gamut
+        TransferST428,          // SMPTE ST 428-1
+        TransferOther = 0xff,
+    };
+
+    enum MatrixCoeffs : uint32_t {
+        MatrixUnspecified,
+        MatrixBT709_5,          // Rec.ITU-R BT.709-5 or equivalent
+        MatrixBT470_6M,         // KR=0.30, KB=0.11 or equivalent
+        MatrixBT601_6,          // Rec.ITU-R BT.601-6 625 or equivalent
+        MatrixSMPTE240M,        // SMPTE 240M or equivalent
+        MatrixBT2020,           // Rec.ITU-R BT.2020 non-constant luminance
+        MatrixBT2020Constant,   // Rec.ITU-R BT.2020 constant luminance
+        MatrixOther = 0xff,
+    };
+
+    // this is in sync with the standard values in graphics.h
+    enum Standard : uint32_t {
+        StandardUnspecified,
+        StandardBT709,                  // PrimariesBT709_5 and MatrixBT709_5
+        StandardBT601_625,              // PrimariesBT601_6_625 and MatrixBT601_6
+        StandardBT601_625_Unadjusted,   // PrimariesBT601_6_625 and KR=0.222, KB=0.071
+        StandardBT601_525,              // PrimariesBT601_6_525 and MatrixBT601_6
+        StandardBT601_525_Unadjusted,   // PrimariesBT601_6_525 and MatrixSMPTE240M
+        StandardBT2020,                 // PrimariesBT2020 and MatrixBT2020
+        StandardBT2020Constant,         // PrimariesBT2020 and MatrixBT2020Constant
+        StandardBT470M,                 // PrimariesBT470_6M and MatrixBT470_6M
+        StandardFilm,                   // PrimariesGenericFilm and KR=0.253, KB=0.068
+        StandardOther = 0xff,
+    };
+
+    Range mRange;                // IN/OUT
+    Primaries mPrimaries;        // IN/OUT
+    Transfer mTransfer;          // IN/OUT
+    MatrixCoeffs mMatrixCoeffs;  // IN/OUT
+};
+
+static_assert(sizeof(ColorAspects) == 16, "wrong struct size");
+
+/**
+ * HDR Metadata.
+ */
+
+// HDR Static Metadata Descriptor as defined by CTA-861-3.
+struct __attribute__ ((__packed__)) HDRStaticInfo {
+    // Static_Metadata_Descriptor_ID
+    enum ID : uint8_t {
+        kType1 = 0, // Static Metadata Type 1
+    } mID;
+
+    struct __attribute__ ((__packed__)) Primaries1 {
+        // values are in units of 0.00002
+        uint16_t x;
+        uint16_t y;
+    };
+
+    // Static Metadata Descriptor Type 1
+    struct __attribute__ ((__packed__)) Type1 {
+        Primaries1 mR; // display primary 0
+        Primaries1 mG; // display primary 1
+        Primaries1 mB; // display primary 2
+        Primaries1 mW; // white point
+        uint16_t mMaxDisplayLuminance; // in cd/m^2
+        uint16_t mMinDisplayLuminance; // in 0.0001 cd/m^2
+        uint16_t mMaxContentLightLevel; // in cd/m^2
+        uint16_t mMaxFrameAverageLightLevel; // in cd/m^2
+    };
+
+    union {
+         Type1 sType1;
+    };
+};
+
+static_assert(sizeof(HDRStaticInfo::Primaries1) == 4, "wrong struct size");
+static_assert(sizeof(HDRStaticInfo::Type1) == 24, "wrong struct size");
+static_assert(sizeof(HDRStaticInfo) == 25, "wrong struct size");
+
+#ifdef STRINGIFY_ENUMS
+
+inline static const char *asString(MediaImage::Type i, const char *def = "??") {
+    switch (i) {
+        case MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN: return "Unknown";
+        case MediaImage::MEDIA_IMAGE_TYPE_YUV:     return "YUV";
+        default:                                   return def;
+    }
+}
+
+inline static const char *asString(MediaImage::PlaneIndex i, const char *def = "??") {
+    switch (i) {
+        case MediaImage::Y: return "Y";
+        case MediaImage::U: return "U";
+        case MediaImage::V: return "V";
+        default:            return def;
+    }
+}
+
+inline static const char *asString(MediaImage2::Type i, const char *def = "??") {
+    switch (i) {
+        case MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN: return "Unknown";
+        case MediaImage2::MEDIA_IMAGE_TYPE_YUV:     return "YUV";
+        case MediaImage2::MEDIA_IMAGE_TYPE_YUVA:    return "YUVA";
+        case MediaImage2::MEDIA_IMAGE_TYPE_RGB:     return "RGB";
+        case MediaImage2::MEDIA_IMAGE_TYPE_RGBA:    return "RGBA";
+        case MediaImage2::MEDIA_IMAGE_TYPE_Y:       return "Y";
+        default:                                    return def;
+    }
+}
+
+inline static char asChar2(
+        MediaImage2::PlaneIndex i, MediaImage2::Type j, char def = '?') {
+    const char *planes = asString(j, NULL);
+    // handle unknown values
+    if (j == MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN || planes == NULL || i >= strlen(planes)) {
+        return def;
+    }
+    return planes[i];
+}
+
+inline static const char *asString(ColorAspects::Range i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::RangeUnspecified: return "Unspecified";
+        case ColorAspects::RangeFull:        return "Full";
+        case ColorAspects::RangeLimited:     return "Limited";
+        case ColorAspects::RangeOther:       return "Other";
+        default:                             return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::Primaries i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::PrimariesUnspecified: return "Unspecified";
+        case ColorAspects::PrimariesBT709_5:     return "BT709_5";
+        case ColorAspects::PrimariesBT470_6M:    return "BT470_6M";
+        case ColorAspects::PrimariesBT601_6_625: return "BT601_6_625";
+        case ColorAspects::PrimariesBT601_6_525: return "BT601_6_525";
+        case ColorAspects::PrimariesGenericFilm: return "GenericFilm";
+        case ColorAspects::PrimariesBT2020:      return "BT2020";
+        case ColorAspects::PrimariesOther:       return "Other";
+        default:                                 return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::Transfer i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::TransferUnspecified: return "Unspecified";
+        case ColorAspects::TransferLinear:      return "Linear";
+        case ColorAspects::TransferSRGB:        return "SRGB";
+        case ColorAspects::TransferSMPTE170M:   return "SMPTE170M";
+        case ColorAspects::TransferGamma22:     return "Gamma22";
+        case ColorAspects::TransferGamma28:     return "Gamma28";
+        case ColorAspects::TransferST2084:      return "ST2084";
+        case ColorAspects::TransferHLG:         return "HLG";
+        case ColorAspects::TransferSMPTE240M:   return "SMPTE240M";
+        case ColorAspects::TransferXvYCC:       return "XvYCC";
+        case ColorAspects::TransferBT1361:      return "BT1361";
+        case ColorAspects::TransferST428:       return "ST428";
+        case ColorAspects::TransferOther:       return "Other";
+        default:                                return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::MatrixCoeffs i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::MatrixUnspecified:    return "Unspecified";
+        case ColorAspects::MatrixBT709_5:        return "BT709_5";
+        case ColorAspects::MatrixBT470_6M:       return "BT470_6M";
+        case ColorAspects::MatrixBT601_6:        return "BT601_6";
+        case ColorAspects::MatrixSMPTE240M:      return "SMPTE240M";
+        case ColorAspects::MatrixBT2020:         return "BT2020";
+        case ColorAspects::MatrixBT2020Constant: return "BT2020Constant";
+        case ColorAspects::MatrixOther:          return "Other";
+        default:                                 return def;
+    }
+}
+
+inline static const char *asString(ColorAspects::Standard i, const char *def = "??") {
+    switch (i) {
+        case ColorAspects::StandardUnspecified:          return "Unspecified";
+        case ColorAspects::StandardBT709:                return "BT709";
+        case ColorAspects::StandardBT601_625:            return "BT601_625";
+        case ColorAspects::StandardBT601_625_Unadjusted: return "BT601_625_Unadjusted";
+        case ColorAspects::StandardBT601_525:            return "BT601_525";
+        case ColorAspects::StandardBT601_525_Unadjusted: return "BT601_525_Unadjusted";
+        case ColorAspects::StandardBT2020:               return "BT2020";
+        case ColorAspects::StandardBT2020Constant:       return "BT2020Constant";
+        case ColorAspects::StandardBT470M:               return "BT470M";
+        case ColorAspects::StandardFilm:                 return "Film";
+        case ColorAspects::StandardOther:                return "Other";
+        default:                                         return def;
+    }
+}
+
+#endif
+
+}  // namespace android
+
+#endif  // VIDEO_API_H_
diff --git a/include/media/openmax/OMX_AsString.h b/include/media/openmax/OMX_AsString.h
index ae8430d..5fb8ca8 100644
--- a/include/media/openmax/OMX_AsString.h
+++ b/include/media/openmax/OMX_AsString.h
@@ -18,6 +18,10 @@
    Each section has its own include guard.  This file should be included AFTER
    the OMX include files. */
 
+#ifdef ANDROID
+namespace android {
+#endif
+
 #ifdef OMX_Audio_h
 /* asString definitions if media/openmax/OMX_Audio.h was included */
 
@@ -288,6 +292,7 @@
 //      case OMX_EventDynamicResourcesAvailable: return "DynamicResourcesAvailable";
 //      case OMX_EventPortFormatDetected:        return "PortFormatDetected";
         case OMX_EventOutputRendered:            return "OutputRendered";
+        case OMX_EventDataSpaceChanged:          return "DataSpaceChanged";
         default:                                 return def;
     }
 }
@@ -521,6 +526,7 @@
         case OMX_IndexParamVideoAndroidVp8Encoder:      return "ParamVideoAndroidVp8Encoder";
         case OMX_IndexParamVideoHevc:                   return "ParamVideoHevc";
 //      case OMX_IndexParamSliceSegments:               return "ParamSliceSegments";
+        case OMX_IndexConfigAndroidIntraRefresh:        return "ConfigAndroidIntraRefresh";
         case OMX_IndexConfigAutoFramerateConversion:    return "ConfigAutoFramerateConversion";
         case OMX_IndexConfigPriority:                   return "ConfigPriority";
         case OMX_IndexConfigOperatingRate:              return "ConfigOperatingRate";
@@ -714,6 +720,7 @@
         case OMX_VIDEO_CodingVP8:        return "VP8";
         case OMX_VIDEO_CodingVP9:        return "VP9";
         case OMX_VIDEO_CodingHEVC:       return "HEVC";
+        case OMX_VIDEO_CodingDolbyVision:return "DolbyVision";
         default:                         return def;
     }
 }
@@ -902,10 +909,11 @@
 
 inline static const char *asString(OMX_VIDEO_HEVCPROFILETYPE i, const char *def = "!!") {
     switch (i) {
-        case OMX_VIDEO_HEVCProfileUnknown: return "Unknown";  // unused
-        case OMX_VIDEO_HEVCProfileMain:    return "Main";
-        case OMX_VIDEO_HEVCProfileMain10:  return "Main10";
-        default:                           return def;
+        case OMX_VIDEO_HEVCProfileUnknown:      return "Unknown";  // unused
+        case OMX_VIDEO_HEVCProfileMain:         return "Main";
+        case OMX_VIDEO_HEVCProfileMain10:       return "Main10";
+        case OMX_VIDEO_HEVCProfileMain10HDR10:  return "Main10HDR10";
+        default:                                return def;
     }
 }
 
@@ -945,3 +953,7 @@
 #endif // AS_STRING_FOR_OMX_VIDEOEXT_H
 
 #endif // OMX_VideoExt_h
+
+#ifdef ANDROID
+} // namespace android
+#endif
diff --git a/include/media/openmax/OMX_Audio.h b/include/media/openmax/OMX_Audio.h
index a0cbd3b..d8bee76 100644
--- a/include/media/openmax/OMX_Audio.h
+++ b/include/media/openmax/OMX_Audio.h
@@ -178,7 +178,7 @@
     OMX_VERSIONTYPE nVersion;         /**< OMX specification version information */
     OMX_U32 nPortIndex;               /**< port that this structure applies to */
     OMX_U32 nChannels;                /**< Number of channels (e.g. 2 for stereo) */
-    OMX_NUMERICALDATATYPE eNumData;   /**< indicates PCM data as signed or unsigned */
+    OMX_NUMERICALDATATYPE eNumData;   /**< indicates PCM data as signed, unsigned or floating pt. */
     OMX_ENDIANTYPE eEndian;           /**< indicates PCM data as little or big endian */
     OMX_BOOL bInterleaved;            /**< True for normal interleaved data; false for
                                            non-interleaved data (e.g. block data) */
diff --git a/include/media/openmax/OMX_AudioExt.h b/include/media/openmax/OMX_AudioExt.h
index 2a1c3f2..05c2232 100644
--- a/include/media/openmax/OMX_AudioExt.h
+++ b/include/media/openmax/OMX_AudioExt.h
@@ -94,6 +94,15 @@
     OMX_S32 nPCMLimiterEnable;     /**< Signal level limiting, 0 for disable, 1 for enable, -1 if unspecified */
 } OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE;
 
+typedef struct OMX_AUDIO_PARAM_ANDROID_PROFILETYPE {
+   OMX_U32 nSize;
+   OMX_VERSIONTYPE nVersion;
+   OMX_U32 nPortIndex;
+   OMX_U32 eProfile;      /**< type is OMX_AUDIO_AACPROFILETYPE or OMX_AUDIO_WMAPROFILETYPE
+                                 depending on context */
+   OMX_U32 nProfileIndex; /**< Used to query for individual profile support information */
+} OMX_AUDIO_PARAM_ANDROID_PROFILETYPE;
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/include/media/openmax/OMX_Core.h b/include/media/openmax/OMX_Core.h
index f746a69..99a7622 100644
--- a/include/media/openmax/OMX_Core.h
+++ b/include/media/openmax/OMX_Core.h
@@ -524,6 +524,21 @@
      *  frame.
      */
     OMX_EventOutputRendered = 0x7F000001,
+
+    /** For framework internal use only: event sent by OMXNodeInstance when it receives a graphic
+     *  input buffer with a new dataspace for encoding. |arg1| will contain the dataspace. |arg2|
+     *  will contain the ColorAspects requested by the component (or framework defaults) using
+     *  the following bitfield layout:
+     *
+     *       +----------+-------------+----------------+------------+
+     *       |   Range  |  Primaries  |  MatrixCoeffs  |  Transfer  |
+     *       +----------+-------------+----------------+------------+
+     *  bits:  31....24   23.......16   15...........8   7........0
+     *
+     *  TODO: We would really need to tie this to an output buffer, but OMX does not provide a
+     *  fool-proof way to do that for video encoders.
+     */
+    OMX_EventDataSpaceChanged,
     OMX_EventMax = 0x7FFFFFFF
 } OMX_EVENTTYPE;
 
diff --git a/include/media/openmax/OMX_IndexExt.h b/include/media/openmax/OMX_IndexExt.h
index 25bea1f..1724576 100644
--- a/include/media/openmax/OMX_IndexExt.h
+++ b/include/media/openmax/OMX_IndexExt.h
@@ -61,6 +61,7 @@
     OMX_IndexParamAudioAndroidOpus,                 /**< reference: OMX_AUDIO_PARAM_ANDROID_OPUSTYPE */
     OMX_IndexParamAudioAndroidAacPresentation,      /**< reference: OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE */
     OMX_IndexParamAudioAndroidEac3,                 /**< reference: OMX_AUDIO_PARAM_ANDROID_EAC3TYPE */
+    OMX_IndexParamAudioProfileQuerySupported,       /**< reference: OMX_AUDIO_PARAM_ANDROID_PROFILETYPE */
 
     /* Image parameters and configurations */
     OMX_IndexExtImageStartUnused = OMX_IndexKhronosExtensions + 0x00500000,
@@ -76,6 +77,7 @@
     OMX_IndexParamVideoAndroidVp8Encoder,           /**< reference: OMX_VIDEO_PARAM_ANDROID_VP8ENCODERTYPE */
     OMX_IndexParamVideoHevc,                        /**< reference: OMX_VIDEO_PARAM_HEVCTYPE */
     OMX_IndexParamSliceSegments,                    /**< reference: OMX_VIDEO_SLICESEGMENTSTYPE */
+    OMX_IndexConfigAndroidIntraRefresh,             /**< reference: OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE */
 
     /* Image & Video common configurations */
     OMX_IndexExtCommonStartUnused = OMX_IndexKhronosExtensions + 0x00700000,
diff --git a/include/media/openmax/OMX_Types.h b/include/media/openmax/OMX_Types.h
index 5afaba0..515e002 100644
--- a/include/media/openmax/OMX_Types.h
+++ b/include/media/openmax/OMX_Types.h
@@ -280,12 +280,18 @@
 
 
 /** The OMX_NUMERICALDATATYPE enumeration is used to indicate if data
-    is signed or unsigned
+    is signed, unsigned or floating point (Android extension).
+
+    Android floating point support policy:
+    If component does not support floating point raw audio, it can reset
+    configuration to signed 16-bit integer (support for which is required.)
+    nBitsPerSample will be set to 32 for float data.
  */
 typedef enum OMX_NUMERICALDATATYPE
 {
     OMX_NumericalDataSigned, /**< signed data */
     OMX_NumericalDataUnsigned, /**< unsigned data */
+    OMX_NumericalDataFloat = 0x7F000001, /**< floating point data */
     OMX_NumercialDataMax = 0x7FFFFFFF
 } OMX_NUMERICALDATATYPE;
 
diff --git a/include/media/openmax/OMX_Video.h b/include/media/openmax/OMX_Video.h
index decc410..ca85cf1 100644
--- a/include/media/openmax/OMX_Video.h
+++ b/include/media/openmax/OMX_Video.h
@@ -88,6 +88,7 @@
     OMX_VIDEO_CodingVP8,        /**< Google VP8, formerly known as On2 VP8 */
     OMX_VIDEO_CodingVP9,        /**< Google VP9 */
     OMX_VIDEO_CodingHEVC,       /**< ITU H.265/HEVC */
+    OMX_VIDEO_CodingDolbyVision,/**< Dolby Vision */
     OMX_VIDEO_CodingKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
     OMX_VIDEO_CodingVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
     OMX_VIDEO_CodingMax = 0x7FFFFFFF
diff --git a/include/media/openmax/OMX_VideoExt.h b/include/media/openmax/OMX_VideoExt.h
index 3971bc5..bf15ee4 100644
--- a/include/media/openmax/OMX_VideoExt.h
+++ b/include/media/openmax/OMX_VideoExt.h
@@ -75,6 +75,39 @@
     OMX_VIDEO_VP8LevelMax = 0x7FFFFFFF
 } OMX_VIDEO_VP8LEVELTYPE;
 
+/** VP9 profiles */
+typedef enum OMX_VIDEO_VP9PROFILETYPE {
+    OMX_VIDEO_VP9Profile0       = 0x1,
+    OMX_VIDEO_VP9Profile1       = 0x2,
+    OMX_VIDEO_VP9Profile2       = 0x4,
+    OMX_VIDEO_VP9Profile3       = 0x8,
+    // HDR profiles also support passing HDR metadata
+    OMX_VIDEO_VP9Profile2HDR    = 0x1000,
+    OMX_VIDEO_VP9Profile3HDR    = 0x2000,
+    OMX_VIDEO_VP9ProfileUnknown = 0x6EFFFFFF,
+    OMX_VIDEO_VP9ProfileMax     = 0x7FFFFFFF
+} OMX_VIDEO_VP9PROFILETYPE;
+
+/** VP9 levels */
+typedef enum OMX_VIDEO_VP9LEVELTYPE {
+    OMX_VIDEO_VP9Level1       = 0x1,
+    OMX_VIDEO_VP9Level11      = 0x2,
+    OMX_VIDEO_VP9Level2       = 0x4,
+    OMX_VIDEO_VP9Level21      = 0x8,
+    OMX_VIDEO_VP9Level3       = 0x10,
+    OMX_VIDEO_VP9Level31      = 0x20,
+    OMX_VIDEO_VP9Level4       = 0x40,
+    OMX_VIDEO_VP9Level41      = 0x80,
+    OMX_VIDEO_VP9Level5       = 0x100,
+    OMX_VIDEO_VP9Level51      = 0x200,
+    OMX_VIDEO_VP9Level52      = 0x400,
+    OMX_VIDEO_VP9Level6       = 0x800,
+    OMX_VIDEO_VP9Level61      = 0x1000,
+    OMX_VIDEO_VP9Level62      = 0x2000,
+    OMX_VIDEO_VP9LevelUnknown = 0x6EFFFFFF,
+    OMX_VIDEO_VP9LevelMax     = 0x7FFFFFFF
+} OMX_VIDEO_VP9LEVELTYPE;
+
 /** VP8 Param */
 typedef struct OMX_VIDEO_PARAM_VP8TYPE {
     OMX_U32 nSize;
@@ -147,10 +180,12 @@
 
 /** HEVC Profile enum type */
 typedef enum OMX_VIDEO_HEVCPROFILETYPE {
-    OMX_VIDEO_HEVCProfileUnknown = 0x0,
-    OMX_VIDEO_HEVCProfileMain    = 0x1,
-    OMX_VIDEO_HEVCProfileMain10  = 0x2,
-    OMX_VIDEO_HEVCProfileMax     = 0x7FFFFFFF
+    OMX_VIDEO_HEVCProfileUnknown      = 0x0,
+    OMX_VIDEO_HEVCProfileMain         = 0x1,
+    OMX_VIDEO_HEVCProfileMain10       = 0x2,
+    // Main10 profile with HDR SEI support.
+    OMX_VIDEO_HEVCProfileMain10HDR10  = 0x1000,
+    OMX_VIDEO_HEVCProfileMax          = 0x7FFFFFFF
 } OMX_VIDEO_HEVCPROFILETYPE;
 
 /** HEVC Level enum type */
@@ -185,13 +220,14 @@
     OMX_VIDEO_HEVCHighTiermax     = 0x7FFFFFFF
 } OMX_VIDEO_HEVCLEVELTYPE;
 
-/** Structure for controlling HEVC video encoding and decoding */
+/** Structure for controlling HEVC video encoding */
 typedef struct OMX_VIDEO_PARAM_HEVCTYPE {
     OMX_U32 nSize;
     OMX_VERSIONTYPE nVersion;
     OMX_U32 nPortIndex;
     OMX_VIDEO_HEVCPROFILETYPE eProfile;
     OMX_VIDEO_HEVCLEVELTYPE eLevel;
+    OMX_U32 nKeyFrameInterval;
 } OMX_VIDEO_PARAM_HEVCTYPE;
 
 /** Structure to define if dependent slice segments should be used */
@@ -216,6 +252,51 @@
                            // following) the render information for the last frame.
 } OMX_VIDEO_RENDEREVENTTYPE;
 
+/** Dolby Vision Profile enum type */
+typedef enum OMX_VIDEO_DOLBYVISIONPROFILETYPE {
+    OMX_VIDEO_DolbyVisionProfileUnknown = 0x0,
+    OMX_VIDEO_DolbyVisionProfileDvavPer = 0x1,
+    OMX_VIDEO_DolbyVisionProfileDvavPen = 0x2,
+    OMX_VIDEO_DolbyVisionProfileDvheDer = 0x4,
+    OMX_VIDEO_DolbyVisionProfileDvheDen = 0x8,
+    OMX_VIDEO_DolbyVisionProfileDvheDtr = 0x10,
+    OMX_VIDEO_DolbyVisionProfileDvheStn = 0x20,
+    OMX_VIDEO_DolbyVisionProfileDvheDth = 0x40,
+    OMX_VIDEO_DolbyVisionProfileDvheDtb = 0x80,
+    OMX_VIDEO_DolbyVisionProfileMax     = 0x7FFFFFFF
+} OMX_VIDEO_DOLBYVISIONPROFILETYPE;
+
+/** Dolby Vision Level enum type */
+typedef enum OMX_VIDEO_DOLBYVISIONLEVELTYPE {
+    OMX_VIDEO_DolbyVisionLevelUnknown = 0x0,
+    OMX_VIDEO_DolbyVisionLevelHd24    = 0x1,
+    OMX_VIDEO_DolbyVisionLevelHd30    = 0x2,
+    OMX_VIDEO_DolbyVisionLevelFhd24   = 0x4,
+    OMX_VIDEO_DolbyVisionLevelFhd30   = 0x8,
+    OMX_VIDEO_DolbyVisionLevelFhd60   = 0x10,
+    OMX_VIDEO_DolbyVisionLevelUhd24   = 0x20,
+    OMX_VIDEO_DolbyVisionLevelUhd30   = 0x40,
+    OMX_VIDEO_DolbyVisionLevelUhd48   = 0x80,
+    OMX_VIDEO_DolbyVisionLevelUhd60   = 0x100,
+    OMX_VIDEO_DolbyVisionLevelmax     = 0x7FFFFFFF
+} OMX_VIDEO_DOLBYVISIONLEVELTYPE;
+
+/**
+ * Structure for configuring video compression intra refresh period
+ *
+ * STRUCT MEMBERS:
+ *  nSize               : Size of the structure in bytes
+ *  nVersion            : OMX specification version information
+ *  nPortIndex          : Port that this structure applies to
+ *  nRefreshPeriod      : Intra refreh period in frames. Value 0 means disable intra refresh
+*/
+typedef struct OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE {
+    OMX_U32 nSize;
+    OMX_VERSIONTYPE nVersion;
+    OMX_U32 nPortIndex;
+    OMX_U32 nRefreshPeriod;
+} OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE;
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
diff --git a/include/powermanager/IPowerManager.h b/include/powermanager/IPowerManager.h
index 91ecc5a..461fad7 100644
--- a/include/powermanager/IPowerManager.h
+++ b/include/powermanager/IPowerManager.h
@@ -25,12 +25,35 @@
 
 // ----------------------------------------------------------------------------
 
-// must be kept in sync with interface defined in IPowerManager.aidl
 class IPowerManager : public IInterface
 {
 public:
+    // These transaction IDs must be kept in sync with the method order from
+    // IPowerManager.aidl.
+    enum {
+        ACQUIRE_WAKE_LOCK            = IBinder::FIRST_CALL_TRANSACTION,
+        ACQUIRE_WAKE_LOCK_UID        = IBinder::FIRST_CALL_TRANSACTION + 1,
+        RELEASE_WAKE_LOCK            = IBinder::FIRST_CALL_TRANSACTION + 2,
+        UPDATE_WAKE_LOCK_UIDS        = IBinder::FIRST_CALL_TRANSACTION + 3,
+        POWER_HINT                   = IBinder::FIRST_CALL_TRANSACTION + 4,
+        UPDATE_WAKE_LOCK_SOURCE      = IBinder::FIRST_CALL_TRANSACTION + 5,
+        IS_WAKE_LOCK_LEVEL_SUPPORTED = IBinder::FIRST_CALL_TRANSACTION + 6,
+        USER_ACTIVITY                = IBinder::FIRST_CALL_TRANSACTION + 7,
+        WAKE_UP                      = IBinder::FIRST_CALL_TRANSACTION + 8,
+        GO_TO_SLEEP                  = IBinder::FIRST_CALL_TRANSACTION + 9,
+        NAP                          = IBinder::FIRST_CALL_TRANSACTION + 10,
+        IS_INTERACTIVE               = IBinder::FIRST_CALL_TRANSACTION + 11,
+        IS_POWER_SAVE_MODE           = IBinder::FIRST_CALL_TRANSACTION + 12,
+        SET_POWER_SAVE_MODE          = IBinder::FIRST_CALL_TRANSACTION + 13,
+        REBOOT                       = IBinder::FIRST_CALL_TRANSACTION + 14,
+        SHUTDOWN                     = IBinder::FIRST_CALL_TRANSACTION + 15,
+        CRASH                        = IBinder::FIRST_CALL_TRANSACTION + 16,
+    };
+
     DECLARE_META_INTERFACE(PowerManager);
 
+    // The parcels created by these methods must be kept in sync with the
+    // corresponding methods from IPowerManager.aidl.
     // FIXME remove the bool isOneWay parameters as they are not oneway in the .aidl
     virtual status_t acquireWakeLock(int flags, const sp<IBinder>& lock, const String16& tag,
             const String16& packageName, bool isOneWay = false) = 0;
@@ -39,8 +62,11 @@
     virtual status_t releaseWakeLock(const sp<IBinder>& lock, int flags, bool isOneWay = false) = 0;
     virtual status_t updateWakeLockUids(const sp<IBinder>& lock, int len, const int *uids,
             bool isOneWay = false) = 0;
-    // oneway in the .aidl
     virtual status_t powerHint(int hintId, int data) = 0;
+    virtual status_t goToSleep(int64_t event_time_ms, int reason, int flags) = 0;
+    virtual status_t reboot(bool confirm, const String16& reason, bool wait) = 0;
+    virtual status_t shutdown(bool confirm, const String16& reason, bool wait) = 0;
+    virtual status_t crash(const String16& message) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/powermanager/PowerManager.h b/include/powermanager/PowerManager.h
index cbddc11..3268b45 100644
--- a/include/powermanager/PowerManager.h
+++ b/include/powermanager/PowerManager.h
@@ -28,8 +28,9 @@
     USER_ACTIVITY_EVENT_OTHER = 0,
     USER_ACTIVITY_EVENT_BUTTON = 1,
     USER_ACTIVITY_EVENT_TOUCH = 2,
+    USER_ACTIVITY_EVENT_ACCESSIBILITY = 3,
 
-    USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_TOUCH, // Last valid event code.
+    USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_ACCESSIBILITY, // Last valid event code.
 };
 
 }; // namespace android
diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h
index cbe8733..92d31d1 100644
--- a/include/private/gui/LayerState.h
+++ b/include/private/gui/LayerState.h
@@ -52,17 +52,21 @@
         eFlagsChanged               = 0x00000040,
         eLayerStackChanged          = 0x00000080,
         eCropChanged                = 0x00000100,
+        eDeferTransaction           = 0x00000200,
+        eFinalCropChanged           = 0x00000400,
+        eOverrideScalingModeChanged = 0x00000800
     };
 
     layer_state_t()
         :   what(0),
             x(0), y(0), z(0), w(0), h(0), layerStack(0),
             alpha(0), flags(0), mask(0),
-            reserved(0)
+            reserved(0), crop(Rect::INVALID_RECT),
+            finalCrop(Rect::INVALID_RECT), frameNumber(0),
+            overrideScalingMode(-1)
     {
         matrix.dsdx = matrix.dtdy = 1.0f;
         matrix.dsdy = matrix.dtdx = 0.0f;
-        crop.makeInvalid();
     }
 
     status_t    write(Parcel& output) const;
@@ -88,6 +92,10 @@
             uint8_t         reserved;
             matrix22_t      matrix;
             Rect            crop;
+            Rect            finalCrop;
+            sp<IBinder>     handle;
+            uint64_t        frameNumber;
+            int32_t         overrideScalingMode;
             // non POD must be last. see write/read
             Region          transparentRegion;
 };
@@ -117,6 +125,8 @@
         eDisplaySizeChanged         = 0x08
     };
 
+    DisplayState();
+
     uint32_t what;
     sp<IBinder> token;
     sp<IGraphicBufferProducer> surface;
diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h
index 8c190dd..84eb100 100644
--- a/include/private/ui/RegionHelper.h
+++ b/include/private/ui/RegionHelper.h
@@ -72,7 +72,7 @@
     }
 
     void operator()(region_rasterizer& rasterizer) {
-        RECT current;
+        RECT current(Rect::EMPTY_RECT);
         do {
             SpannerInner spannerInner(spanner.lhs, spanner.rhs);
             int inside = spanner.next(current.top, current.bottom);
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
deleted file mode 100644
index 6b66d5f..0000000
--- a/include/ui/FramebufferNativeWindow.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
-#warning "FramebufferNativeWindow is deprecated"
-#endif
-
-#ifndef ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
-#define ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
-
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <EGL/egl.h>
-
-#include <utils/threads.h>
-#include <utils/String8.h>
-
-#include <ui/ANativeObjectBase.h>
-#include <ui/Rect.h>
-
-#define MIN_NUM_FRAME_BUFFERS  2
-#define MAX_NUM_FRAME_BUFFERS  3
-
-extern "C" EGLNativeWindowType android_createDisplaySurface(void);
-
-// ---------------------------------------------------------------------------
-namespace android {
-// ---------------------------------------------------------------------------
-
-class Surface;
-class NativeBuffer;
-
-// ---------------------------------------------------------------------------
-
-class FramebufferNativeWindow 
-    : public ANativeObjectBase<
-        ANativeWindow, 
-        FramebufferNativeWindow, 
-        LightRefBase<FramebufferNativeWindow> >
-{
-public:
-    FramebufferNativeWindow(); 
-
-    framebuffer_device_t const * getDevice() const { return fbDev; } 
-
-    bool isUpdateOnDemand() const { return mUpdateOnDemand; }
-    status_t setUpdateRectangle(const Rect& updateRect);
-    status_t compositionComplete();
-
-    void dump(String8& result);
-
-    // for debugging only
-    int getCurrentBufferIndex() const;
-
-private:
-    friend class LightRefBase<FramebufferNativeWindow>;    
-    ~FramebufferNativeWindow(); // this class cannot be overloaded
-    static int setSwapInterval(ANativeWindow* window, int interval);
-    static int dequeueBuffer(ANativeWindow* window, ANativeWindowBuffer** buffer, int* fenceFd);
-    static int queueBuffer(ANativeWindow* window, ANativeWindowBuffer* buffer, int fenceFd);
-    static int query(const ANativeWindow* window, int what, int* value);
-    static int perform(ANativeWindow* window, int operation, ...);
-
-    static int dequeueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer** buffer);
-    static int queueBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
-    static int lockBuffer_DEPRECATED(ANativeWindow* window, ANativeWindowBuffer* buffer);
-
-    framebuffer_device_t* fbDev;
-    alloc_device_t* grDev;
-
-    sp<NativeBuffer> buffers[MAX_NUM_FRAME_BUFFERS];
-    sp<NativeBuffer> front;
-    
-    mutable Mutex mutex;
-    Condition mCondition;
-    int32_t mNumBuffers;
-    int32_t mNumFreeBuffers;
-    int32_t mBufferHead;
-    int32_t mCurrentBufferIndex;
-    bool mUpdateOnDemand;
-};
-    
-// ---------------------------------------------------------------------------
-}; // namespace android
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_FRAMEBUFFER_NATIVE_WINDOW_H
-
diff --git a/include/ui/HdrCapabilities.h b/include/ui/HdrCapabilities.h
new file mode 100644
index 0000000..a7cd5fb
--- /dev/null
+++ b/include/ui/HdrCapabilities.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_UI_HDR_CAPABILTIES_H
+#define ANDROID_UI_HDR_CAPABILTIES_H
+
+#include <binder/Parcelable.h>
+
+namespace android {
+
+class HdrCapabilities : public Parcelable
+{
+public:
+    HdrCapabilities(const std::vector<int32_t /*android_hdr_t*/>& types,
+            float maxLuminance, float maxAverageLuminance, float minLuminance)
+      : mSupportedHdrTypes(types),
+        mMaxLuminance(maxLuminance),
+        mMaxAverageLuminance(maxAverageLuminance),
+        mMinLuminance(minLuminance) {}
+
+    // Make this move-constructable and move-assignable
+    HdrCapabilities(HdrCapabilities&& other) = default;
+    HdrCapabilities& operator=(HdrCapabilities&& other) = default;
+
+    HdrCapabilities()
+      : mSupportedHdrTypes(),
+        mMaxLuminance(-1.0f),
+        mMaxAverageLuminance(-1.0f),
+        mMinLuminance(-1.0f) {}
+
+    virtual ~HdrCapabilities() = default;
+
+    const std::vector<int32_t /*android_hdr_t*/>& getSupportedHdrTypes() const {
+        return mSupportedHdrTypes;
+    }
+    float getDesiredMaxLuminance() const { return mMaxLuminance; }
+    float getDesiredMaxAverageLuminance() const { return mMaxAverageLuminance; }
+    float getDesiredMinLuminance() const { return mMinLuminance; }
+
+    // Parcelable interface
+    virtual status_t writeToParcel(Parcel* parcel) const override;
+    virtual status_t readFromParcel(const Parcel* parcel) override;
+
+private:
+    std::vector<int32_t /*android_hdr_t*/> mSupportedHdrTypes;
+    float mMaxLuminance;
+    float mMaxAverageLuminance;
+    float mMinLuminance;
+};
+
+} // namespace android
+
+#endif
diff --git a/include/ui/Rect.h b/include/ui/Rect.h
index 3886f93..a8513a9 100644
--- a/include/ui/Rect.h
+++ b/include/ui/Rect.h
@@ -32,21 +32,15 @@
     typedef ARect::value_type value_type;
 
     static const Rect INVALID_RECT;
+    static const Rect EMPTY_RECT;
 
     // we don't provide copy-ctor and operator= on purpose
     // because we want the compiler generated versions
 
-    inline Rect() {
-      left = right = top = bottom = 0;
-    }
+    inline Rect() : Rect(INVALID_RECT) {}
 
-    inline Rect(int32_t w, int32_t h) {
-        left = top = 0;
-        right = w;
-        bottom = h;
-    }
-
-    inline Rect(uint32_t w, uint32_t h) {
+    template <typename T>
+    inline Rect(T w, T h) {
         if (w > INT32_MAX) {
             ALOG(LOG_WARN, "Rect",
                     "Width %u too large for Rect class, clamping", w);
@@ -58,8 +52,8 @@
             h = INT32_MAX;
         }
         left = top = 0;
-        right = w;
-        bottom = h;
+        right = static_cast<int32_t>(w);
+        bottom = static_cast<int32_t>(h);
     }
 
     inline Rect(int32_t l, int32_t t, int32_t r, int32_t b) {
diff --git a/include/ui/Region.h b/include/ui/Region.h
index 2a14918..810f098 100644
--- a/include/ui/Region.h
+++ b/include/ui/Region.h
@@ -28,7 +28,6 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-class SharedBuffer;
 class String8;
 
 // ---------------------------------------------------------------------------
@@ -130,11 +129,6 @@
     // Region object.
     Rect const* getArray(size_t* count) const;
 
-    // returns a SharedBuffer as well as the number of rects.
-    // ownership is transfered to the caller.
-    // the caller must call SharedBuffer::release() to free the memory.
-    SharedBuffer const* getSharedBuffer(size_t* count) const;
-
     /* no user serviceable parts here... */
 
             // add a rectangle to the internal list. This rectangle must
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index d5860ef..14be920 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -23,19 +23,23 @@
     IAppOpsService.cpp \
     IBatteryStats.cpp \
     IInterface.cpp \
+    IMediaResourceMonitor.cpp \
     IMemory.cpp \
     IPCThreadState.cpp \
     IPermissionController.cpp \
     IProcessInfoService.cpp \
-    ProcessInfoService.cpp \
+    IResultReceiver.cpp \
     IServiceManager.cpp \
-    MemoryDealer.cpp \
     MemoryBase.cpp \
+    MemoryDealer.cpp \
     MemoryHeapBase.cpp \
     Parcel.cpp \
     PermissionCache.cpp \
+    PersistableBundle.cpp \
+    ProcessInfoService.cpp \
     ProcessState.cpp \
     Static.cpp \
+    Status.cpp \
     TextOutput.cpp \
 
 LOCAL_PATH:= $(call my-dir)
@@ -43,6 +47,9 @@
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbinder
 LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
 LOCAL_SRC_FILES := $(sources)
 ifneq ($(TARGET_USES_64_BIT_BINDER),true)
 ifneq ($(TARGET_IS_64_BIT),true)
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index e4d8201..9a061a0 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -28,7 +28,7 @@
 
 static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
     pthread_mutex_lock(&gTokenMutex);
-    if (gToken == NULL) {
+    if (gToken == NULL || gToken->pingBinder() != NO_ERROR) {
         gToken = service->getToken(new BBinder());
     }
     pthread_mutex_unlock(&gTokenMutex);
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 9d200fb..c4d47ca 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -16,10 +16,11 @@
 
 #include <binder/Binder.h>
 
-#include <stdatomic.h>
+#include <atomic>
 #include <utils/misc.h>
 #include <binder/BpBinder.h>
 #include <binder/IInterface.h>
+#include <binder/IResultReceiver.h>
 #include <binder/Parcel.h>
 
 #include <stdio.h>
@@ -59,6 +60,24 @@
     return false;
 }
 
+
+status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int err,
+    Vector<String16>& args, const sp<IResultReceiver>& resultReceiver)
+{
+    Parcel send;
+    Parcel reply;
+    send.writeFileDescriptor(in);
+    send.writeFileDescriptor(out);
+    send.writeFileDescriptor(err);
+    const size_t numArgs = args.size();
+    send.writeInt32(numArgs);
+    for (size_t i = 0; i < numArgs; i++) {
+        send.writeString16(args[i]);
+    }
+    send.writeStrongBinder(resultReceiver != NULL ? IInterface::asBinder(resultReceiver) : NULL);
+    return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
+}
+
 // ---------------------------------------------------------------------------
 
 class BBinder::Extras
@@ -70,9 +89,8 @@
 
 // ---------------------------------------------------------------------------
 
-BBinder::BBinder()
+BBinder::BBinder() : mExtras(nullptr)
 {
-  atomic_init(&mExtras, static_cast<uintptr_t>(0));
 }
 
 bool BBinder::isBinderAlive() const
@@ -130,7 +148,7 @@
     return INVALID_OPERATION;
 }
 
-    status_t BBinder::dump(int /*fd*/, const Vector<String16>& /*args*/)
+status_t BBinder::dump(int /*fd*/, const Vector<String16>& /*args*/)
 {
     return NO_ERROR;
 }
@@ -139,19 +157,16 @@
     const void* objectID, void* object, void* cleanupCookie,
     object_cleanup_func func)
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    atomic_load_explicit(&mExtras, memory_order_acquire));
+    Extras* e = mExtras.load(std::memory_order_acquire);
 
     if (!e) {
         e = new Extras;
-        uintptr_t expected = 0;
-        if (!atomic_compare_exchange_strong_explicit(
-                                        &mExtras, &expected,
-                                        reinterpret_cast<uintptr_t>(e),
-                                        memory_order_release,
-                                        memory_order_acquire)) {
+        Extras* expected = nullptr;
+        if (!mExtras.compare_exchange_strong(expected, e,
+                                             std::memory_order_release,
+                                             std::memory_order_acquire)) {
             delete e;
-            e = reinterpret_cast<Extras*>(expected);  // Filled in by CAS
+            e = expected;  // Filled in by CAS
         }
         if (e == 0) return; // out of memory
     }
@@ -160,18 +175,9 @@
     e->mObjects.attach(objectID, object, cleanupCookie, func);
 }
 
-// The C11 standard doesn't allow atomic loads from const fields,
-// though C++11 does.  Fudge it until standards get straightened out.
-static inline uintptr_t load_const_atomic(const atomic_uintptr_t* p,
-                                          memory_order mo) {
-    atomic_uintptr_t* non_const_p = const_cast<atomic_uintptr_t*>(p);
-    return atomic_load_explicit(non_const_p, mo);
-}
-
 void* BBinder::findObject(const void* objectID) const
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    load_const_atomic(&mExtras, memory_order_acquire));
+    Extras* e = mExtras.load(std::memory_order_acquire);
     if (!e) return NULL;
 
     AutoMutex _l(e->mLock);
@@ -180,8 +186,7 @@
 
 void BBinder::detachObject(const void* objectID)
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    atomic_load_explicit(&mExtras, memory_order_acquire));
+    Extras* e = mExtras.load(std::memory_order_acquire);
     if (!e) return;
 
     AutoMutex _l(e->mLock);
@@ -195,8 +200,7 @@
 
 BBinder::~BBinder()
 {
-    Extras* e = reinterpret_cast<Extras*>(
-                    atomic_load_explicit(&mExtras, memory_order_relaxed));
+    Extras* e = mExtras.load(std::memory_order_relaxed);
     if (e) delete e;
 }
 
@@ -219,6 +223,25 @@
             return dump(fd, args);
         }
 
+        case SHELL_COMMAND_TRANSACTION: {
+            int in = data.readFileDescriptor();
+            int out = data.readFileDescriptor();
+            int err = data.readFileDescriptor();
+            int argc = data.readInt32();
+            Vector<String16> args;
+            for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+               args.add(data.readString16());
+            }
+            sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
+                    data.readStrongBinder());
+
+            // XXX can't add virtuals until binaries are updated.
+            //return shellCommand(in, out, err, args, resultReceiver);
+            if (resultReceiver != NULL) {
+                resultReceiver->send(INVALID_OPERATION);
+            }
+        }
+
         case SYSPROPS_TRANSACTION: {
             report_sysprop_change();
             return NO_ERROR;
@@ -252,7 +275,7 @@
 BpRefBase::~BpRefBase()
 {
     if (mRemote) {
-        if (!(mState&kRemoteAcquired)) {
+        if (!(mState.load(std::memory_order_relaxed)&kRemoteAcquired)) {
             mRemote->decStrong(this);
         }
         mRefs->decWeak(this);
@@ -261,7 +284,7 @@
 
 void BpRefBase::onFirstRef()
 {
-    android_atomic_or(kRemoteAcquired, &mState);
+    mState.fetch_or(kRemoteAcquired, std::memory_order_relaxed);
 }
 
 void BpRefBase::onLastStrongRef(const void* /*id*/)
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 345ba20..c0e0296 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -20,6 +20,7 @@
 #include <binder/BpBinder.h>
 
 #include <binder/IPCThreadState.h>
+#include <binder/IResultReceiver.h>
 #include <utils/Log.h>
 
 #include <stdio.h>
diff --git a/libs/binder/Debug.cpp b/libs/binder/Debug.cpp
index bdb7182..a8f2da5 100644
--- a/libs/binder/Debug.cpp
+++ b/libs/binder/Debug.cpp
@@ -138,7 +138,7 @@
         *pos = 0;
         return pos;
     }
-    
+
     if( fullContext ) {
         *pos++ = '0';
         *pos++ = 'x';
@@ -167,21 +167,21 @@
     if (func == NULL) func = defaultPrintFunc;
 
     size_t offset;
-    
+
     unsigned char *pos = (unsigned char *)buf;
-    
+
     if (pos == NULL) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(NULL)");
         return;
     }
-    
+
     if (length == 0) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         func(cookie, "(empty)");
         return;
     }
-    
+
     if ((int32_t)length < 0) {
         if (singleLineBytesCutoff < 0) func(cookie, "\n");
         char buf[64];
@@ -189,12 +189,12 @@
         func(cookie, buf);
         return;
     }
-    
+
     char buffer[256];
     static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
-    
+
     if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
-    
+
     const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
     bool newLine = false;
     if (cStyle) {
@@ -205,7 +205,7 @@
         func(cookie, "\n");
         newLine = true;
     }
-    
+
     for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
         long remain = length;
 
@@ -217,21 +217,20 @@
 
         size_t index;
         size_t word;
-        
+
         for (word = 0; word < bytesPerLine; ) {
 
             const size_t startIndex = word+(alignment-(alignment?1:0));
-            const ssize_t dir = -1;
 
             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
-            
+
                 if (!cStyle) {
                     if (index == 0 && word > 0 && alignment > 0) {
                         *c++ = ' ';
                     }
-                
+
                     if (remain-- > 0) {
-                        const unsigned char val = *(pos+startIndex+(index*dir));
+                        const unsigned char val = *(pos+startIndex-index);
                         *c++ = makehexdigit(val>>4);
                         *c++ = makehexdigit(val);
                     } else if (!oneLine) {
@@ -248,14 +247,14 @@
                             *c++ = '0';
                             *c++ = 'x';
                         }
-                        const unsigned char val = *(pos+startIndex+(index*dir));
+                        const unsigned char val = *(pos+startIndex-index);
                         *c++ = makehexdigit(val>>4);
                         *c++ = makehexdigit(val);
                         remain--;
                     }
                 }
             }
-            
+
             word += index;
         }
 
@@ -272,7 +271,7 @@
                     *c++ = ' ';
                 }
             }
-            
+
             *c++ = '\'';
             if (length > bytesPerLine) *c++ = '\n';
         } else {
@@ -284,7 +283,7 @@
         *c = 0;
         func(cookie, buffer);
         newLine = true;
-        
+
         if (length <= bytesPerLine) break;
         length -= bytesPerLine;
     }
diff --git a/libs/binder/IMediaResourceMonitor.cpp b/libs/binder/IMediaResourceMonitor.cpp
new file mode 100644
index 0000000..4800f5b
--- /dev/null
+++ b/libs/binder/IMediaResourceMonitor.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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 <binder/IMediaResourceMonitor.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <sys/types.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpMediaResourceMonitor : public BpInterface<IMediaResourceMonitor> {
+public:
+    BpMediaResourceMonitor(const sp<IBinder>& impl)
+        : BpInterface<IMediaResourceMonitor>(impl) {}
+
+    virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaResourceMonitor::getInterfaceDescriptor());
+        data.writeInt32(pid);
+        data.writeInt32(type);
+        remote()->transact(NOTIFY_RESOURCE_GRANTED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor");
+
+// ----------------------------------------------------------------------
+
+status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags) {
+    switch(code) {
+        case NOTIFY_RESOURCE_GRANTED: {
+            CHECK_INTERFACE(IMediaResourceMonitor, data, reply);
+            int32_t pid = data.readInt32();
+            const int32_t type = data.readInt32();
+            notifyResourceGranted(/*in*/ pid, /*in*/ type);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index af18e11..d90798f 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -24,12 +24,14 @@
 
 #include <cutils/sched_policy.h>
 #include <utils/Log.h>
+#include <utils/SystemClock.h>
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
 #include <private/binder/Static.h>
 
 #include <errno.h>
+#include <inttypes.h>
 #include <pthread.h>
 #include <sched.h>
 #include <signal.h>
@@ -287,12 +289,18 @@
         return new IPCThreadState;
     }
     
-    if (gShutdown) return NULL;
+    if (gShutdown) {
+        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
+        return NULL;
+    }
     
     pthread_mutex_lock(&gTLSMutex);
     if (!gHaveTLS) {
-        if (pthread_key_create(&gTLS, threadDestructor) != 0) {
+        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
+        if (key_create_value != 0) {
             pthread_mutex_unlock(&gTLSMutex);
+            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
+                    strerror(key_create_value));
             return NULL;
         }
         gHaveTLS = true;
@@ -428,12 +436,25 @@
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
         mProcess->mExecutingThreadsCount++;
+        if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
+                mProcess->mStarvationStartTimeMs == 0) {
+            mProcess->mStarvationStartTimeMs = uptimeMillis();
+        }
         pthread_mutex_unlock(&mProcess->mThreadCountLock);
 
         result = executeCommand(cmd);
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
         mProcess->mExecutingThreadsCount--;
+        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
+                mProcess->mStarvationStartTimeMs != 0) {
+            int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
+            if (starvationTimeMs > 100) {
+                ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
+                      mProcess->mMaxThreads, starvationTimeMs);
+            }
+            mProcess->mStarvationStartTimeMs = 0;
+        }
         pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
         pthread_mutex_unlock(&mProcess->mThreadCountLock);
 
@@ -852,7 +873,7 @@
         IF_LOG_COMMANDS() {
             alog << "About to read/write, write size = " << mOut.dataSize() << endl;
         }
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
             err = NO_ERROR;
         else
@@ -1166,7 +1187,7 @@
         IPCThreadState* const self = static_cast<IPCThreadState*>(st);
         if (self) {
                 self->flushCommands();
-#if defined(HAVE_ANDROID_OS)
+#if defined(__ANDROID__)
         if (self->mProcess->mDriverFD > 0) {
             ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0);
         }
diff --git a/libs/binder/IProcessInfoService.cpp b/libs/binder/IProcessInfoService.cpp
index d86eb27..76508b8 100644
--- a/libs/binder/IProcessInfoService.cpp
+++ b/libs/binder/IProcessInfoService.cpp
@@ -49,46 +49,43 @@
         return reply.readInt32();
     }
 
+    virtual status_t getProcessStatesAndOomScoresFromPids(size_t length,
+            /*in*/ int32_t* pids, /*out*/ int32_t* states, /*out*/ int32_t* scores)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IProcessInfoService::getInterfaceDescriptor());
+        data.writeInt32Array(length, pids);
+        // write length of output arrays, used by java AIDL stubs
+        data.writeInt32(length);
+        data.writeInt32(length);
+        status_t err = remote()->transact(
+                GET_PROCESS_STATES_AND_OOM_SCORES_FROM_PIDS, data, &reply);
+        if (err != NO_ERROR
+                || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+            return err;
+        }
+        int32_t replyLen = reply.readInt32();
+        if (static_cast<size_t>(replyLen) != length) {
+            return NOT_ENOUGH_DATA;
+        }
+        if (replyLen > 0 && (err = reply.read(
+                states, length * sizeof(*states))) != NO_ERROR) {
+            return err;
+        }
+        replyLen = reply.readInt32();
+        if (static_cast<size_t>(replyLen) != length) {
+            return NOT_ENOUGH_DATA;
+        }
+        if (replyLen > 0 && (err = reply.read(
+                scores, length * sizeof(*scores))) != NO_ERROR) {
+            return err;
+        }
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
 
 // ----------------------------------------------------------------------
 
-status_t BnProcessInfoService::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
-        uint32_t flags) {
-    switch(code) {
-        case GET_PROCESS_STATES_FROM_PIDS: {
-            CHECK_INTERFACE(IProcessInfoService, data, reply);
-            int32_t arrayLen = data.readInt32();
-            if (arrayLen <= 0) {
-                reply->writeNoException();
-                reply->writeInt32(0);
-                reply->writeInt32(NOT_ENOUGH_DATA);
-                return NO_ERROR;
-            }
-
-            size_t len = static_cast<size_t>(arrayLen);
-            int32_t pids[len];
-            status_t res = data.read(pids, len * sizeof(*pids));
-
-            // Ignore output array length returned in the parcel here, as the states array must
-            // always be the same length as the input PIDs array.
-            int32_t states[len];
-            for (size_t i = 0; i < len; i++) states[i] = -1;
-            if (res == NO_ERROR) {
-                res = getProcessStatesFromPids(len, /*in*/ pids, /*out*/ states);
-            }
-            reply->writeNoException();
-            reply->writeInt32Array(len, states);
-            reply->writeInt32(res);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
-// ----------------------------------------------------------------------
-
 }; // namespace android
diff --git a/libs/binder/IResultReceiver.cpp b/libs/binder/IResultReceiver.cpp
new file mode 100644
index 0000000..2a22b69
--- /dev/null
+++ b/libs/binder/IResultReceiver.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "ResultReceiver"
+
+#include <binder/IResultReceiver.h>
+
+#include <utils/Log.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+#include <private/binder/Static.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpResultReceiver : public BpInterface<IResultReceiver>
+{
+public:
+    BpResultReceiver(const sp<IBinder>& impl)
+        : BpInterface<IResultReceiver>(impl)
+    {
+    }
+
+    virtual void send(int32_t resultCode) {
+        Parcel data;
+        data.writeInterfaceToken(IResultReceiver::getInterfaceDescriptor());
+        data.writeInt32(resultCode);
+        remote()->transact(OP_SEND, data, NULL, IBinder::FLAG_ONEWAY);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver");
+
+// ----------------------------------------------------------------------
+
+status_t BnResultReceiver::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch(code) {
+        case OP_SEND: {
+            CHECK_INTERFACE(IResultReceiver, data, reply);
+            int32_t resultCode = data.readInt32();
+            send(resultCode);
+            if (reply != NULL) {
+                reply->writeNoException();
+            }
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+}; // namespace android
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 3c716df..61f24d6 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -33,7 +33,7 @@
 sp<IServiceManager> defaultServiceManager()
 {
     if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
-    
+
     {
         AutoMutex _l(gDefaultServiceManagerLock);
         while (gDefaultServiceManager == NULL) {
@@ -43,7 +43,7 @@
                 sleep(1);
         }
     }
-    
+
     return gDefaultServiceManager;
 }
 
@@ -67,11 +67,16 @@
 
 bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
 {
+#ifdef __BRILLO__
+    // Brillo doesn't currently run ActivityManager or support framework permissions.
+    return true;
+#endif
+
     sp<IPermissionController> pc;
     gDefaultServiceManagerLock.lock();
     pc = gPermissionController;
     gDefaultServiceManagerLock.unlock();
-    
+
     int64_t startTime = 0;
 
     while (true) {
@@ -85,14 +90,14 @@
                 }
                 return res;
             }
-            
+
             // Is this a permission failure, or did the controller go away?
             if (IInterface::asBinder(pc)->isBinderAlive()) {
                 ALOGW("Permission failure: %s from uid=%d pid=%d",
                         String8(permission).string(), uid, pid);
                 return false;
             }
-            
+
             // Object is dead!
             gDefaultServiceManagerLock.lock();
             if (gPermissionController == pc) {
@@ -100,7 +105,7 @@
             }
             gDefaultServiceManagerLock.unlock();
         }
-    
+
         // Need to retrieve the permission controller.
         sp<IBinder> binder = defaultServiceManager()->checkService(_permission);
         if (binder == NULL) {
@@ -113,7 +118,7 @@
             sleep(1);
         } else {
             pc = interface_cast<IPermissionController>(binder);
-            // Install the new permission controller, and try again.        
+            // Install the new permission controller, and try again.
             gDefaultServiceManagerLock.lock();
             gPermissionController = pc;
             gDefaultServiceManagerLock.unlock();
@@ -184,48 +189,4 @@
 
 IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
 
-// ----------------------------------------------------------------------
-
-status_t BnServiceManager::onTransact(
-    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
-{
-    //printf("ServiceManager received: "); data.print();
-    switch(code) {
-        case GET_SERVICE_TRANSACTION: {
-            CHECK_INTERFACE(IServiceManager, data, reply);
-            String16 which = data.readString16();
-            sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which);
-            reply->writeStrongBinder(b);
-            return NO_ERROR;
-        } break;
-        case CHECK_SERVICE_TRANSACTION: {
-            CHECK_INTERFACE(IServiceManager, data, reply);
-            String16 which = data.readString16();
-            sp<IBinder> b = const_cast<BnServiceManager*>(this)->checkService(which);
-            reply->writeStrongBinder(b);
-            return NO_ERROR;
-        } break;
-        case ADD_SERVICE_TRANSACTION: {
-            CHECK_INTERFACE(IServiceManager, data, reply);
-            String16 which = data.readString16();
-            sp<IBinder> b = data.readStrongBinder();
-            status_t err = addService(which, b);
-            reply->writeInt32(err);
-            return NO_ERROR;
-        } break;
-        case LIST_SERVICES_TRANSACTION: {
-            CHECK_INTERFACE(IServiceManager, data, reply);
-            Vector<String16> list = listServices();
-            const size_t N = list.size();
-            reply->writeInt32(N);
-            for (size_t i=0; i<N; i++) {
-                reply->writeString16(list[i]);
-            }
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
-    }
-}
-
 }; // namespace android
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index 8739625..51eac11 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -135,6 +135,8 @@
     void        dump(const char* what) const;
     void        dump(String8& res, const char* what) const;
 
+    static size_t getAllocationAlignment() { return kMemoryAlign; }
+
 private:
 
     struct chunk_t {
@@ -264,6 +266,12 @@
     return mAllocator;
 }
 
+// static
+size_t MemoryDealer::getAllocationAlignment()
+{
+    return SimpleBestFitAllocator::getAllocationAlignment();
+}
+
 // ----------------------------------------------------------------------------
 
 // align all the memory blocks on a cache-line boundary
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 1429a5c..a0161b3 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -18,13 +18,16 @@
 //#define LOG_NDEBUG 0
 
 #include <errno.h>
+#include <fcntl.h>
 #include <inttypes.h>
+#include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/resource.h>
 #include <unistd.h>
 
 #include <binder/Binder.h>
@@ -32,6 +35,7 @@
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
+#include <binder/Status.h>
 #include <binder/TextOutput.h>
 
 #include <cutils/ashmem.h>
@@ -71,9 +75,6 @@
 // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
 #define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
 
-// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
-#define EX_HAS_REPLY_HEADER -128
-
 // XXX This can be made public if we want to provide
 // support for typed data.
 struct small_flat_data
@@ -88,6 +89,8 @@
 static size_t gParcelGlobalAllocSize = 0;
 static size_t gParcelGlobalAllocCount = 0;
 
+static size_t gMaxFds = 0;
+
 // Maximum size of a blob to transfer in-place.
 static const size_t BLOB_INPLACE_LIMIT = 16 * 1024;
 
@@ -97,6 +100,32 @@
     BLOB_ASHMEM_MUTABLE = 2,
 };
 
+static dev_t ashmem_rdev()
+{
+    static dev_t __ashmem_rdev;
+    static pthread_mutex_t __ashmem_rdev_lock = PTHREAD_MUTEX_INITIALIZER;
+
+    pthread_mutex_lock(&__ashmem_rdev_lock);
+
+    dev_t rdev = __ashmem_rdev;
+    if (!rdev) {
+        int fd = TEMP_FAILURE_RETRY(open("/dev/ashmem", O_RDONLY));
+        if (fd >= 0) {
+            struct stat st;
+
+            int ret = TEMP_FAILURE_RETRY(fstat(fd, &st));
+            close(fd);
+            if ((ret >= 0) && S_ISCHR(st.st_mode)) {
+                rdev = __ashmem_rdev = st.st_rdev;
+            }
+        }
+    }
+
+    pthread_mutex_unlock(&__ashmem_rdev_lock);
+
+    return rdev;
+}
+
 void acquire_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
 {
@@ -128,7 +157,7 @@
             if ((obj.cookie != 0) && (outAshmemSize != NULL)) {
                 struct stat st;
                 int ret = fstat(obj.handle, &st);
-                if (!ret && S_ISCHR(st.st_mode)) {
+                if (!ret && S_ISCHR(st.st_mode) && (st.st_rdev == ashmem_rdev())) {
                     // If we own an ashmem fd, keep track of how much memory it refers to.
                     int size = ashmem_get_size_region(obj.handle);
                     if (size > 0) {
@@ -181,7 +210,7 @@
                 if (outAshmemSize != NULL) {
                     struct stat st;
                     int ret = fstat(obj.handle, &st);
-                    if (!ret && S_ISCHR(st.st_mode)) {
+                    if (!ret && S_ISCHR(st.st_mode) && (st.st_rdev == ashmem_rdev())) {
                         int size = ashmem_get_size_region(obj.handle);
                         if (size > 0) {
                             *outAshmemSize -= size;
@@ -386,13 +415,11 @@
 
 size_t Parcel::dataAvail() const
 {
-    // TODO: decide what to do about the possibility that this can
-    // report an available-data size that exceeds a Java int's max
-    // positive value, causing havoc.  Fortunately this will only
-    // happen if someone constructs a Parcel containing more than two
-    // gigabytes of data, which on typical phone hardware is simply
-    // not possible.
-    return dataSize() - dataPosition();
+    size_t result = dataSize() - dataPosition();
+    if (result > INT32_MAX) {
+        abort();
+    }
+    return result;
 }
 
 size_t Parcel::dataPosition() const
@@ -753,6 +780,174 @@
     return NULL;
 }
 
+status_t Parcel::writeUtf8AsUtf16(const std::string& str) {
+    const uint8_t* strData = (uint8_t*)str.data();
+    const size_t strLen= str.length();
+    const ssize_t utf16Len = utf8_to_utf16_length(strData, strLen);
+    if (utf16Len < 0 || utf16Len> std::numeric_limits<int32_t>::max()) {
+        return BAD_VALUE;
+    }
+
+    status_t err = writeInt32(utf16Len);
+    if (err) {
+        return err;
+    }
+
+    // Allocate enough bytes to hold our converted string and its terminating NULL.
+    void* dst = writeInplace((utf16Len + 1) * sizeof(char16_t));
+    if (!dst) {
+        return NO_MEMORY;
+    }
+
+    utf8_to_utf16(strData, strLen, (char16_t*)dst);
+
+    return NO_ERROR;
+}
+
+status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) {
+  if (!str) {
+    return writeInt32(-1);
+  }
+  return writeUtf8AsUtf16(*str);
+}
+
+namespace {
+
+template<typename T>
+status_t writeByteVectorInternal(Parcel* parcel, const std::vector<T>& val)
+{
+    status_t status;
+    if (val.size() > std::numeric_limits<int32_t>::max()) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    status = parcel->writeInt32(val.size());
+    if (status != OK) {
+        return status;
+    }
+
+    void* data = parcel->writeInplace(val.size());
+    if (!data) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    memcpy(data, val.data(), val.size());
+    return status;
+}
+
+template<typename T>
+status_t writeByteVectorInternalPtr(Parcel* parcel,
+                                    const std::unique_ptr<std::vector<T>>& val)
+{
+    if (!val) {
+        return parcel->writeInt32(-1);
+    }
+
+    return writeByteVectorInternal(parcel, *val);
+}
+
+}  // namespace
+
+status_t Parcel::writeByteVector(const std::vector<int8_t>& val) {
+    return writeByteVectorInternal(this, val);
+}
+
+status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val)
+{
+    return writeByteVectorInternalPtr(this, val);
+}
+
+status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) {
+    return writeByteVectorInternal(this, val);
+}
+
+status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val)
+{
+    return writeByteVectorInternalPtr(this, val);
+}
+
+status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val)
+{
+    return writeTypedVector(val, &Parcel::writeInt32);
+}
+
+status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeInt32);
+}
+
+status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val)
+{
+    return writeTypedVector(val, &Parcel::writeInt64);
+}
+
+status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeInt64);
+}
+
+status_t Parcel::writeFloatVector(const std::vector<float>& val)
+{
+    return writeTypedVector(val, &Parcel::writeFloat);
+}
+
+status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeFloat);
+}
+
+status_t Parcel::writeDoubleVector(const std::vector<double>& val)
+{
+    return writeTypedVector(val, &Parcel::writeDouble);
+}
+
+status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeDouble);
+}
+
+status_t Parcel::writeBoolVector(const std::vector<bool>& val)
+{
+    return writeTypedVector(val, &Parcel::writeBool);
+}
+
+status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeBool);
+}
+
+status_t Parcel::writeCharVector(const std::vector<char16_t>& val)
+{
+    return writeTypedVector(val, &Parcel::writeChar);
+}
+
+status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeChar);
+}
+
+status_t Parcel::writeString16Vector(const std::vector<String16>& val)
+{
+    return writeTypedVector(val, &Parcel::writeString16);
+}
+
+status_t Parcel::writeString16Vector(
+        const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeString16);
+}
+
+status_t Parcel::writeUtf8VectorAsUtf16Vector(
+                        const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) {
+    return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16);
+}
+
+status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) {
+    return writeTypedVector(val, &Parcel::writeUtf8AsUtf16);
+}
+
 status_t Parcel::writeInt32(int32_t val)
 {
     return writeAligned(val);
@@ -796,6 +991,21 @@
     return ret;
 }
 
+status_t Parcel::writeBool(bool val)
+{
+    return writeInt32(int32_t(val));
+}
+
+status_t Parcel::writeChar(char16_t val)
+{
+    return writeInt32(int32_t(val));
+}
+
+status_t Parcel::writeByte(int8_t val)
+{
+    return writeInt32(int32_t(val));
+}
+
 status_t Parcel::writeInt64(int64_t val)
 {
     return writeAligned(val);
@@ -854,6 +1064,15 @@
     return err;
 }
 
+status_t Parcel::writeString16(const std::unique_ptr<String16>& str)
+{
+    if (!str) {
+        return writeInt32(-1);
+    }
+
+    return writeString16(*str);
+}
+
 status_t Parcel::writeString16(const String16& str)
 {
     return writeString16(str.string(), str.size());
@@ -882,11 +1101,45 @@
     return flatten_binder(ProcessState::self(), val, this);
 }
 
+status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val)
+{
+    return writeTypedVector(val, &Parcel::writeStrongBinder);
+}
+
+status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val)
+{
+    return writeNullableTypedVector(val, &Parcel::writeStrongBinder);
+}
+
+status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readStrongBinder);
+}
+
+status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const {
+    return readTypedVector(val, &Parcel::readStrongBinder);
+}
+
 status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
 {
     return flatten_binder(ProcessState::self(), val, this);
 }
 
+status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) {
+    if (!parcelable) {
+        return writeInt32(0);
+    }
+
+    return writeParcelable(*parcelable);
+}
+
+status_t Parcel::writeParcelable(const Parcelable& parcelable) {
+    status_t status = writeInt32(1);  // parcelable is not null.
+    if (status != OK) {
+        return status;
+    }
+    return parcelable.writeToParcel(this);
+}
+
 status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
     if (!handle || handle->version != sizeof(native_handle))
@@ -928,12 +1181,24 @@
         return -errno;
     }
     status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
-    if (err) {
+    if (err != OK) {
         close(dupFd);
     }
     return err;
 }
 
+status_t Parcel::writeUniqueFileDescriptor(const ScopedFd& fd) {
+    return writeDupFileDescriptor(fd.get());
+}
+
+status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<ScopedFd>& val) {
+    return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor);
+}
+
+status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<ScopedFd>>& val) {
+    return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor);
+}
+
 status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
     if (len > INT32_MAX) {
@@ -1006,7 +1271,7 @@
     const size_t len = val.getFlattenedSize();
     const size_t fd_count = val.getFdCount();
 
-    if ((len > INT32_MAX) || (fd_count > INT32_MAX)) {
+    if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
         return BAD_VALUE;
@@ -1025,7 +1290,11 @@
 
     int* fds = NULL;
     if (fd_count) {
-        fds = new int[fd_count];
+        fds = new (std::nothrow) int[fd_count];
+        if (fds == nullptr) {
+            ALOGE("write: failed to allocate requested %zu fds", fd_count);
+            return BAD_VALUE;
+        }
     }
 
     err = val.flatten(buf, len, fds, fd_count);
@@ -1085,7 +1354,8 @@
 
 status_t Parcel::writeNoException()
 {
-    return writeInt32(0);
+    binder::Status status;
+    return status.writeToParcel(this);
 }
 
 void Parcel::remove(size_t /*start*/, size_t /*amt*/)
@@ -1168,6 +1438,193 @@
     return err;
 }
 
+namespace {
+
+template<typename T>
+status_t readByteVectorInternal(const Parcel* parcel,
+                                std::vector<T>* val) {
+    val->clear();
+
+    int32_t size;
+    status_t status = parcel->readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        status = UNEXPECTED_NULL;
+        return status;
+    }
+    if (size_t(size) > parcel->dataAvail()) {
+        status = BAD_VALUE;
+        return status;
+    }
+
+    const void* data = parcel->readInplace(size);
+    if (!data) {
+        status = BAD_VALUE;
+        return status;
+    }
+    val->resize(size);
+    memcpy(val->data(), data, size);
+
+    return status;
+}
+
+template<typename T>
+status_t readByteVectorInternalPtr(
+        const Parcel* parcel,
+        std::unique_ptr<std::vector<T>>* val) {
+    const int32_t start = parcel->dataPosition();
+    int32_t size;
+    status_t status = parcel->readInt32(&size);
+    val->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    parcel->setDataPosition(start);
+    val->reset(new (std::nothrow) std::vector<T>());
+
+    status = readByteVectorInternal(parcel, val->get());
+
+    if (status != OK) {
+        val->reset();
+    }
+
+    return status;
+}
+
+}  // namespace
+
+status_t Parcel::readByteVector(std::vector<int8_t>* val) const {
+    return readByteVectorInternal(this, val);
+}
+
+status_t Parcel::readByteVector(std::vector<uint8_t>* val) const {
+    return readByteVectorInternal(this, val);
+}
+
+status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const {
+    return readByteVectorInternalPtr(this, val);
+}
+
+status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const {
+    return readByteVectorInternalPtr(this, val);
+}
+
+status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readInt32);
+}
+
+status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const {
+    return readTypedVector(val, &Parcel::readInt32);
+}
+
+status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readInt64);
+}
+
+status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const {
+    return readTypedVector(val, &Parcel::readInt64);
+}
+
+status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readFloat);
+}
+
+status_t Parcel::readFloatVector(std::vector<float>* val) const {
+    return readTypedVector(val, &Parcel::readFloat);
+}
+
+status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readDouble);
+}
+
+status_t Parcel::readDoubleVector(std::vector<double>* val) const {
+    return readTypedVector(val, &Parcel::readDouble);
+}
+
+status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const {
+    const int32_t start = dataPosition();
+    int32_t size;
+    status_t status = readInt32(&size);
+    val->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    setDataPosition(start);
+    val->reset(new (std::nothrow) std::vector<bool>());
+
+    status = readBoolVector(val->get());
+
+    if (status != OK) {
+        val->reset();
+    }
+
+    return status;
+}
+
+status_t Parcel::readBoolVector(std::vector<bool>* val) const {
+    int32_t size;
+    status_t status = readInt32(&size);
+
+    if (status != OK) {
+        return status;
+    }
+
+    if (size < 0) {
+        return UNEXPECTED_NULL;
+    }
+
+    val->resize(size);
+
+    /* C++ bool handling means a vector of bools isn't necessarily addressable
+     * (we might use individual bits)
+     */
+    bool data;
+    for (int32_t i = 0; i < size; ++i) {
+        status = readBool(&data);
+        (*val)[i] = data;
+
+        if (status != OK) {
+            return status;
+        }
+    }
+
+    return OK;
+}
+
+status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readChar);
+}
+
+status_t Parcel::readCharVector(std::vector<char16_t>* val) const {
+    return readTypedVector(val, &Parcel::readChar);
+}
+
+status_t Parcel::readString16Vector(
+        std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readString16);
+}
+
+status_t Parcel::readString16Vector(std::vector<String16>* val) const {
+    return readTypedVector(val, &Parcel::readString16);
+}
+
+status_t Parcel::readUtf8VectorFromUtf16Vector(
+        std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16);
+}
+
+status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const {
+    return readTypedVector(val, &Parcel::readUtf8FromUtf16);
+}
+
 status_t Parcel::readInt32(int32_t *pArg) const
 {
     return readAligned(pArg);
@@ -1286,6 +1743,84 @@
     return readAligned<intptr_t>();
 }
 
+status_t Parcel::readBool(bool *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = (tmp != 0);
+    return ret;
+}
+
+bool Parcel::readBool() const
+{
+    return readInt32() != 0;
+}
+
+status_t Parcel::readChar(char16_t *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = char16_t(tmp);
+    return ret;
+}
+
+char16_t Parcel::readChar() const
+{
+    return char16_t(readInt32());
+}
+
+status_t Parcel::readByte(int8_t *pArg) const
+{
+    int32_t tmp;
+    status_t ret = readInt32(&tmp);
+    *pArg = int8_t(tmp);
+    return ret;
+}
+
+int8_t Parcel::readByte() const
+{
+    return int8_t(readInt32());
+}
+
+status_t Parcel::readUtf8FromUtf16(std::string* str) const {
+    size_t utf16Size = 0;
+    const char16_t* src = readString16Inplace(&utf16Size);
+    if (!src) {
+        return UNEXPECTED_NULL;
+    }
+
+    // Save ourselves the trouble, we're done.
+    if (utf16Size == 0u) {
+        str->clear();
+       return NO_ERROR;
+    }
+
+    ssize_t utf8Size = utf16_to_utf8_length(src, utf16Size);
+    if (utf8Size < 0) {
+        return BAD_VALUE;
+    }
+    // Note that while it is probably safe to assume string::resize keeps a
+    // spare byte around for the trailing null, we're going to be explicit.
+    str->resize(utf8Size + 1);
+    utf16_to_utf8(src, utf16Size, &((*str)[0]));
+    str->resize(utf8Size);
+    return NO_ERROR;
+}
+
+status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const {
+    const int32_t start = dataPosition();
+    int32_t size;
+    status_t status = readInt32(&size);
+    str->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    setDataPosition(start);
+    str->reset(new (std::nothrow) std::string());
+    return readUtf8FromUtf16(str->get());
+}
 
 const char* Parcel::readCString() const
 {
@@ -1324,6 +1859,42 @@
     return String16();
 }
 
+status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const
+{
+    const int32_t start = dataPosition();
+    int32_t size;
+    status_t status = readInt32(&size);
+    pArg->reset();
+
+    if (status != OK || size < 0) {
+        return status;
+    }
+
+    setDataPosition(start);
+    pArg->reset(new (std::nothrow) String16());
+
+    status = readString16(pArg->get());
+
+    if (status != OK) {
+        pArg->reset();
+    }
+
+    return status;
+}
+
+status_t Parcel::readString16(String16* pArg) const
+{
+    size_t len;
+    const char16_t* str = readString16Inplace(&len);
+    if (str) {
+        pArg->setTo(str, len);
+        return 0;
+    } else {
+        *pArg = String16();
+        return UNEXPECTED_NULL;
+    }
+}
+
 const char16_t* Parcel::readString16Inplace(size_t* outLen) const
 {
     int32_t size = readInt32();
@@ -1339,10 +1910,15 @@
     return NULL;
 }
 
+status_t Parcel::readStrongBinder(sp<IBinder>* val) const
+{
+    return unflatten_binder(ProcessState::self(), *this, val);
+}
+
 sp<IBinder> Parcel::readStrongBinder() const
 {
     sp<IBinder> val;
-    unflatten_binder(ProcessState::self(), *this, &val);
+    readStrongBinder(&val);
     return val;
 }
 
@@ -1353,20 +1929,23 @@
     return val;
 }
 
+status_t Parcel::readParcelable(Parcelable* parcelable) const {
+    int32_t have_parcelable = 0;
+    status_t status = readInt32(&have_parcelable);
+    if (status != OK) {
+        return status;
+    }
+    if (!have_parcelable) {
+        return UNEXPECTED_NULL;
+    }
+    return parcelable->readFromParcel(this);
+}
+
 int32_t Parcel::readExceptionCode() const
 {
-  int32_t exception_code = readAligned<int32_t>();
-  if (exception_code == EX_HAS_REPLY_HEADER) {
-    int32_t header_start = dataPosition();
-    int32_t header_size = readAligned<int32_t>();
-    // Skip over fat responses headers.  Not used (or propagated) in
-    // native code
-    setDataPosition(header_start + header_size);
-    // And fat response headers are currently only used when there are no
-    // exceptions, so return no error:
-    return 0;
-  }
-  return exception_code;
+    binder::Status status;
+    status.readFromParcel(*this);
+    return status.exceptionCode();
 }
 
 native_handle* Parcel::readNativeHandle() const
@@ -1400,16 +1979,40 @@
 int Parcel::readFileDescriptor() const
 {
     const flat_binder_object* flat = readObject(true);
-    if (flat) {
-        switch (flat->type) {
-            case BINDER_TYPE_FD:
-                //ALOGI("Returning file descriptor %ld from parcel %p", flat->handle, this);
-                return flat->handle;
-        }
+
+    if (flat && flat->type == BINDER_TYPE_FD) {
+        return flat->handle;
     }
+
     return BAD_TYPE;
 }
 
+status_t Parcel::readUniqueFileDescriptor(ScopedFd* val) const
+{
+    int got = readFileDescriptor();
+
+    if (got == BAD_TYPE) {
+        return BAD_TYPE;
+    }
+
+    val->reset(dup(got));
+
+    if (val->get() < 0) {
+        return BAD_VALUE;
+    }
+
+    return OK;
+}
+
+
+status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<ScopedFd>>* val) const {
+    return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor);
+}
+
+status_t Parcel::readUniqueFileDescriptorVector(std::vector<ScopedFd>* val) const {
+    return readTypedVector(val, &Parcel::readUniqueFileDescriptor);
+}
+
 status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
 {
     int32_t blobType;
@@ -1444,7 +2047,7 @@
     const size_t len = this->readInt32();
     const size_t fd_count = this->readInt32();
 
-    if (len > INT32_MAX) {
+    if ((len > INT32_MAX) || (fd_count >= gMaxFds)) {
         // don't accept size_t values which may have come from an
         // inadvertent conversion from a negative int.
         return BAD_VALUE;
@@ -1457,7 +2060,11 @@
 
     int* fds = NULL;
     if (fd_count) {
-        fds = new int[fd_count];
+        fds = new (std::nothrow) int[fd_count];
+        if (fds == nullptr) {
+            ALOGE("read: failed to allocate requested %zu fds", fd_count);
+            return BAD_VALUE;
+        }
     }
 
     status_t err = NO_ERROR;
@@ -1679,8 +2286,14 @@
         if (mData) {
             LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity);
             pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
-            gParcelGlobalAllocSize -= mDataCapacity;
-            gParcelGlobalAllocCount--;
+            if (mDataCapacity <= gParcelGlobalAllocSize) {
+              gParcelGlobalAllocSize = gParcelGlobalAllocSize - mDataCapacity;
+            } else {
+              gParcelGlobalAllocSize = 0;
+            }
+            if (gParcelGlobalAllocCount > 0) {
+              gParcelGlobalAllocCount--;
+            }
             pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
             free(mData);
         }
@@ -1728,6 +2341,9 @@
         pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
         gParcelGlobalAllocSize += desired;
         gParcelGlobalAllocSize -= mDataCapacity;
+        if (!mData) {
+            gParcelGlobalAllocCount++;
+        }
         pthread_mutex_unlock(&gParcelGlobalAllocSizeLock);
         mData = data;
         mDataCapacity = desired;
@@ -1925,6 +2541,18 @@
     mAllowFds = true;
     mOwner = NULL;
     mOpenAshmemSize = 0;
+
+    // racing multiple init leads only to multiple identical write
+    if (gMaxFds == 0) {
+        struct rlimit result;
+        if (!getrlimit(RLIMIT_NOFILE, &result)) {
+            gMaxFds = (size_t)result.rlim_cur;
+            //ALOGI("parcel fd limit set to %zu", gMaxFds);
+        } else {
+            ALOGW("Unable to getrlimit: %s", strerror(errno));
+            gMaxFds = 1024;
+        }
+    }
 }
 
 void Parcel::scanForFds() const
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
new file mode 100644
index 0000000..aef791c
--- /dev/null
+++ b/libs/binder/PersistableBundle.cpp
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "PersistableBundle"
+
+#include <binder/PersistableBundle.h>
+
+#include <limits>
+
+#include <binder/IBinder.h>
+#include <binder/Parcel.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+
+using android::BAD_TYPE;
+using android::BAD_VALUE;
+using android::NO_ERROR;
+using android::Parcel;
+using android::sp;
+using android::status_t;
+using android::UNEXPECTED_NULL;
+
+enum {
+    // Keep in sync with BUNDLE_MAGIC in frameworks/base/core/java/android/os/BaseBundle.java.
+    BUNDLE_MAGIC = 0x4C444E42,
+};
+
+enum {
+    // Keep in sync with frameworks/base/core/java/android/os/Parcel.java.
+    VAL_STRING = 0,
+    VAL_INTEGER = 1,
+    VAL_LONG = 6,
+    VAL_DOUBLE = 8,
+    VAL_BOOLEAN = 9,
+    VAL_STRINGARRAY = 14,
+    VAL_INTARRAY = 18,
+    VAL_LONGARRAY = 19,
+    VAL_BOOLEANARRAY = 23,
+    VAL_PERSISTABLEBUNDLE = 25,
+    VAL_DOUBLEARRAY = 28,
+};
+
+namespace {
+template <typename T>
+bool getValue(const android::String16& key, T* out, const std::map<android::String16, T>& map) {
+    const auto& it = map.find(key);
+    if (it == map.end()) return false;
+    *out = it->second;
+    return true;
+}
+}  // namespace
+
+namespace android {
+
+namespace os {
+
+#define RETURN_IF_FAILED(calledOnce)                                     \
+    {                                                                    \
+        status_t returnStatus = calledOnce;                              \
+        if (returnStatus) {                                              \
+            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+            return returnStatus;                                         \
+         }                                                               \
+    }
+
+#define RETURN_IF_ENTRY_ERASED(map, key)                                 \
+    {                                                                    \
+        size_t num_erased = map.erase(key);                              \
+        if (num_erased) {                                                \
+            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
+            return num_erased;                                           \
+         }                                                               \
+    }
+
+status_t PersistableBundle::writeToParcel(Parcel* parcel) const {
+    /*
+     * Keep implementation in sync with writeToParcelInner() in
+     * frameworks/base/core/java/android/os/BaseBundle.java.
+     */
+
+    // Special case for empty bundles.
+    if (empty()) {
+        RETURN_IF_FAILED(parcel->writeInt32(0));
+        return NO_ERROR;
+    }
+
+    size_t length_pos = parcel->dataPosition();
+    RETURN_IF_FAILED(parcel->writeInt32(1));  // dummy, will hold length
+    RETURN_IF_FAILED(parcel->writeInt32(BUNDLE_MAGIC));
+
+    size_t start_pos = parcel->dataPosition();
+    RETURN_IF_FAILED(writeToParcelInner(parcel));
+    size_t end_pos = parcel->dataPosition();
+
+    // Backpatch length. This length value includes the length header.
+    parcel->setDataPosition(length_pos);
+    size_t length = end_pos - start_pos;
+    if (length > std::numeric_limits<int32_t>::max()) {
+        ALOGE("Parcel length (%zu) too large to store in 32-bit signed int", length);
+        return BAD_VALUE;
+    }
+    RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(length)));
+    parcel->setDataPosition(end_pos);
+    return NO_ERROR;
+}
+
+status_t PersistableBundle::readFromParcel(const Parcel* parcel) {
+    /*
+     * Keep implementation in sync with readFromParcelInner() in
+     * frameworks/base/core/java/android/os/BaseBundle.java.
+     */
+    int32_t length = parcel->readInt32();
+    if (length < 0) {
+        ALOGE("Bad length in parcel: %d", length);
+        return UNEXPECTED_NULL;
+    }
+
+    return readFromParcelInner(parcel, static_cast<size_t>(length));
+}
+
+bool PersistableBundle::empty() const {
+    return size() == 0u;
+}
+
+size_t PersistableBundle::size() const {
+    return (mBoolMap.size() +
+            mIntMap.size() +
+            mLongMap.size() +
+            mDoubleMap.size() +
+            mStringMap.size() +
+            mBoolVectorMap.size() +
+            mIntVectorMap.size() +
+            mLongVectorMap.size() +
+            mDoubleVectorMap.size() +
+            mStringVectorMap.size() +
+            mPersistableBundleMap.size());
+}
+
+size_t PersistableBundle::erase(const String16& key) {
+    RETURN_IF_ENTRY_ERASED(mBoolMap, key);
+    RETURN_IF_ENTRY_ERASED(mIntMap, key);
+    RETURN_IF_ENTRY_ERASED(mLongMap, key);
+    RETURN_IF_ENTRY_ERASED(mDoubleMap, key);
+    RETURN_IF_ENTRY_ERASED(mStringMap, key);
+    RETURN_IF_ENTRY_ERASED(mBoolVectorMap, key);
+    RETURN_IF_ENTRY_ERASED(mIntVectorMap, key);
+    RETURN_IF_ENTRY_ERASED(mLongVectorMap, key);
+    RETURN_IF_ENTRY_ERASED(mDoubleVectorMap, key);
+    RETURN_IF_ENTRY_ERASED(mStringVectorMap, key);
+    return mPersistableBundleMap.erase(key);
+}
+
+void PersistableBundle::putBoolean(const String16& key, bool value) {
+    erase(key);
+    mBoolMap[key] = value;
+}
+
+void PersistableBundle::putInt(const String16& key, int32_t value) {
+    erase(key);
+    mIntMap[key] = value;
+}
+
+void PersistableBundle::putLong(const String16& key, int64_t value) {
+    erase(key);
+    mLongMap[key] = value;
+}
+
+void PersistableBundle::putDouble(const String16& key, double value) {
+    erase(key);
+    mDoubleMap[key] = value;
+}
+
+void PersistableBundle::putString(const String16& key, const String16& value) {
+    erase(key);
+    mStringMap[key] = value;
+}
+
+void PersistableBundle::putBooleanVector(const String16& key, const std::vector<bool>& value) {
+    erase(key);
+    mBoolVectorMap[key] = value;
+}
+
+void PersistableBundle::putIntVector(const String16& key, const std::vector<int32_t>& value) {
+    erase(key);
+    mIntVectorMap[key] = value;
+}
+
+void PersistableBundle::putLongVector(const String16& key, const std::vector<int64_t>& value) {
+    erase(key);
+    mLongVectorMap[key] = value;
+}
+
+void PersistableBundle::putDoubleVector(const String16& key, const std::vector<double>& value) {
+    erase(key);
+    mDoubleVectorMap[key] = value;
+}
+
+void PersistableBundle::putStringVector(const String16& key, const std::vector<String16>& value) {
+    erase(key);
+    mStringVectorMap[key] = value;
+}
+
+void PersistableBundle::putPersistableBundle(const String16& key, const PersistableBundle& value) {
+    erase(key);
+    mPersistableBundleMap[key] = value;
+}
+
+bool PersistableBundle::getBoolean(const String16& key, bool* out) const {
+    return getValue(key, out, mBoolMap);
+}
+
+bool PersistableBundle::getInt(const String16& key, int32_t* out) const {
+    return getValue(key, out, mIntMap);
+}
+
+bool PersistableBundle::getLong(const String16& key, int64_t* out) const {
+    return getValue(key, out, mLongMap);
+}
+
+bool PersistableBundle::getDouble(const String16& key, double* out) const {
+    return getValue(key, out, mDoubleMap);
+}
+
+bool PersistableBundle::getString(const String16& key, String16* out) const {
+    return getValue(key, out, mStringMap);
+}
+
+bool PersistableBundle::getBooleanVector(const String16& key, std::vector<bool>* out) const {
+    return getValue(key, out, mBoolVectorMap);
+}
+
+bool PersistableBundle::getIntVector(const String16& key, std::vector<int32_t>* out) const {
+    return getValue(key, out, mIntVectorMap);
+}
+
+bool PersistableBundle::getLongVector(const String16& key, std::vector<int64_t>* out) const {
+    return getValue(key, out, mLongVectorMap);
+}
+
+bool PersistableBundle::getDoubleVector(const String16& key, std::vector<double>* out) const {
+    return getValue(key, out, mDoubleVectorMap);
+}
+
+bool PersistableBundle::getStringVector(const String16& key, std::vector<String16>* out) const {
+    return getValue(key, out, mStringVectorMap);
+}
+
+bool PersistableBundle::getPersistableBundle(const String16& key, PersistableBundle* out) const {
+    return getValue(key, out, mPersistableBundleMap);
+}
+
+status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const {
+    /*
+     * To keep this implementation in sync with writeArrayMapInternal() in
+     * frameworks/base/core/java/android/os/Parcel.java, the number of key
+     * value pairs must be written into the parcel before writing the key-value
+     * pairs themselves.
+     */
+    size_t num_entries = size();
+    if (num_entries > std::numeric_limits<int32_t>::max()) {
+        ALOGE("The size of this PersistableBundle (%zu) too large to store in 32-bit signed int",
+              num_entries);
+        return BAD_VALUE;
+    }
+    RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(num_entries)));
+
+    for (const auto& key_val_pair : mBoolMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_BOOLEAN));
+        RETURN_IF_FAILED(parcel->writeBool(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mIntMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_INTEGER));
+        RETURN_IF_FAILED(parcel->writeInt32(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mLongMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_LONG));
+        RETURN_IF_FAILED(parcel->writeInt64(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mDoubleMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_DOUBLE));
+        RETURN_IF_FAILED(parcel->writeDouble(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mStringMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_STRING));
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mBoolVectorMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_BOOLEANARRAY));
+        RETURN_IF_FAILED(parcel->writeBoolVector(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mIntVectorMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_INTARRAY));
+        RETURN_IF_FAILED(parcel->writeInt32Vector(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mLongVectorMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_LONGARRAY));
+        RETURN_IF_FAILED(parcel->writeInt64Vector(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mDoubleVectorMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_DOUBLEARRAY));
+        RETURN_IF_FAILED(parcel->writeDoubleVector(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mStringVectorMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_STRINGARRAY));
+        RETURN_IF_FAILED(parcel->writeString16Vector(key_val_pair.second));
+    }
+    for (const auto& key_val_pair : mPersistableBundleMap) {
+        RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
+        RETURN_IF_FAILED(parcel->writeInt32(VAL_PERSISTABLEBUNDLE));
+        RETURN_IF_FAILED(key_val_pair.second.writeToParcel(parcel));
+    }
+    return NO_ERROR;
+}
+
+status_t PersistableBundle::readFromParcelInner(const Parcel* parcel, size_t length) {
+    /*
+     * Note: we don't actually use length for anything other than an empty PersistableBundle
+     * check, since we do not actually need to copy in an entire Parcel, unlike in the Java
+     * implementation.
+     */
+    if (length == 0) {
+        // Empty PersistableBundle or end of data.
+        return NO_ERROR;
+    }
+
+    int32_t magic;
+    RETURN_IF_FAILED(parcel->readInt32(&magic));
+    if (magic != BUNDLE_MAGIC) {
+        ALOGE("Bad magic number for PersistableBundle: 0x%08x", magic);
+        return BAD_VALUE;
+    }
+
+    /*
+     * To keep this implementation in sync with unparcel() in
+     * frameworks/base/core/java/android/os/BaseBundle.java, the number of
+     * key-value pairs must be read from the parcel before reading the key-value
+     * pairs themselves.
+     */
+    int32_t num_entries;
+    RETURN_IF_FAILED(parcel->readInt32(&num_entries));
+
+    for (; num_entries > 0; --num_entries) {
+        size_t start_pos = parcel->dataPosition();
+        String16 key;
+        int32_t value_type;
+        RETURN_IF_FAILED(parcel->readString16(&key));
+        RETURN_IF_FAILED(parcel->readInt32(&value_type));
+
+        /*
+         * We assume that both the C++ and Java APIs ensure that all keys in a PersistableBundle
+         * are unique.
+         */
+        switch (value_type) {
+            case VAL_STRING: {
+                RETURN_IF_FAILED(parcel->readString16(&mStringMap[key]));
+                break;
+            }
+            case VAL_INTEGER: {
+                RETURN_IF_FAILED(parcel->readInt32(&mIntMap[key]));
+                break;
+            }
+            case VAL_LONG: {
+                RETURN_IF_FAILED(parcel->readInt64(&mLongMap[key]));
+                break;
+            }
+            case VAL_DOUBLE: {
+                RETURN_IF_FAILED(parcel->readDouble(&mDoubleMap[key]));
+                break;
+            }
+            case VAL_BOOLEAN: {
+                RETURN_IF_FAILED(parcel->readBool(&mBoolMap[key]));
+                break;
+            }
+            case VAL_STRINGARRAY: {
+                RETURN_IF_FAILED(parcel->readString16Vector(&mStringVectorMap[key]));
+                break;
+            }
+            case VAL_INTARRAY: {
+                RETURN_IF_FAILED(parcel->readInt32Vector(&mIntVectorMap[key]));
+                break;
+            }
+            case VAL_LONGARRAY: {
+                RETURN_IF_FAILED(parcel->readInt64Vector(&mLongVectorMap[key]));
+                break;
+            }
+            case VAL_BOOLEANARRAY: {
+                RETURN_IF_FAILED(parcel->readBoolVector(&mBoolVectorMap[key]));
+                break;
+            }
+            case VAL_PERSISTABLEBUNDLE: {
+                RETURN_IF_FAILED(mPersistableBundleMap[key].readFromParcel(parcel));
+                break;
+            }
+            case VAL_DOUBLEARRAY: {
+                RETURN_IF_FAILED(parcel->readDoubleVector(&mDoubleVectorMap[key]));
+                break;
+            }
+            default: {
+                ALOGE("Unrecognized type: %d", value_type);
+                return BAD_TYPE;
+                break;
+            }
+        }
+    }
+
+    return NO_ERROR;
+}
+
+}  // namespace os
+
+}  // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 016d3c5..f13f49f 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -40,12 +40,12 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
 #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
 #define DEFAULT_MAX_BINDER_THREADS 15
 
-
-// ---------------------------------------------------------------------------
+// -------------------------------------------------------------------------
 
 namespace android {
 
@@ -278,8 +278,9 @@
 
 String8 ProcessState::makeBinderThreadName() {
     int32_t s = android_atomic_add(1, &mThreadPoolSeq);
+    pid_t pid = getpid();
     String8 name;
-    name.appendFormat("Binder_%X", s);
+    name.appendFormat("Binder:%d_%X", pid, s);
     return name;
 }
 
@@ -310,9 +311,8 @@
 
 static int open_driver()
 {
-    int fd = open("/dev/binder", O_RDWR);
+    int fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
     if (fd >= 0) {
-        fcntl(fd, F_SETFD, FD_CLOEXEC);
         int vers = 0;
         status_t result = ioctl(fd, BINDER_VERSION, &vers);
         if (result == -1) {
@@ -343,6 +343,7 @@
     , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
     , mExecutingThreadsCount(0)
     , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
+    , mStarvationStartTimeMs(0)
     , mManagesContexts(false)
     , mBinderContextCheckFunc(NULL)
     , mBinderContextUserData(NULL)
@@ -350,10 +351,6 @@
     , mThreadPoolSeq(1)
 {
     if (mDriverFD >= 0) {
-        // XXX Ideally, there should be a specific define for whether we
-        // have mmap (or whether we could possibly have the kernel module
-        // availabla).
-#if !defined(HAVE_WIN32_IPC)
         // mmap the binder, providing a chunk of virtual address space to receive transactions.
         mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
         if (mVMStart == MAP_FAILED) {
@@ -362,9 +359,6 @@
             close(mDriverFD);
             mDriverFD = -1;
         }
-#else
-        mDriverFD = -1;
-#endif
     }
 
     LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");
diff --git a/libs/binder/Status.cpp b/libs/binder/Status.cpp
new file mode 100644
index 0000000..d3520d6
--- /dev/null
+++ b/libs/binder/Status.cpp
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 <binder/Status.h>
+
+namespace android {
+namespace binder {
+
+Status Status::ok() {
+    return Status();
+}
+
+Status Status::fromExceptionCode(int32_t exceptionCode) {
+    return Status(exceptionCode, OK);
+}
+
+Status Status::fromExceptionCode(int32_t exceptionCode,
+                                 const String8& message) {
+    return Status(exceptionCode, OK, message);
+}
+
+Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode) {
+    return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode);
+}
+
+Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
+                                        const String8& message) {
+    return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode, message);
+}
+
+Status Status::fromStatusT(status_t status) {
+    Status ret;
+    ret.setFromStatusT(status);
+    return ret;
+}
+
+Status::Status(int32_t exceptionCode, int32_t errorCode)
+    : mException(exceptionCode),
+      mErrorCode(errorCode) {}
+
+Status::Status(int32_t exceptionCode, int32_t errorCode, const String8& message)
+    : mException(exceptionCode),
+      mErrorCode(errorCode),
+      mMessage(message) {}
+
+status_t Status::readFromParcel(const Parcel& parcel) {
+    status_t status = parcel.readInt32(&mException);
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+
+    // Skip over fat response headers.  Not used (or propagated) in native code.
+    if (mException == EX_HAS_REPLY_HEADER) {
+        // Note that the header size includes the 4 byte size field.
+        const int32_t header_start = parcel.dataPosition();
+        int32_t header_size;
+        status = parcel.readInt32(&header_size);
+        if (status != OK) {
+            setFromStatusT(status);
+            return status;
+        }
+        parcel.setDataPosition(header_start + header_size);
+        // And fat response headers are currently only used when there are no
+        // exceptions, so act like there was no error.
+        mException = EX_NONE;
+    }
+
+    if (mException == EX_NONE) {
+        return status;
+    }
+
+    // The remote threw an exception.  Get the message back.
+    String16 message;
+    status = parcel.readString16(&message);
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+    mMessage = String8(message);
+
+    if (mException == EX_SERVICE_SPECIFIC) {
+        status = parcel.readInt32(&mErrorCode);
+    }
+    if (status != OK) {
+        setFromStatusT(status);
+        return status;
+    }
+
+    return status;
+}
+
+status_t Status::writeToParcel(Parcel* parcel) const {
+    // Something really bad has happened, and we're not going to even
+    // try returning rich error data.
+    if (mException == EX_TRANSACTION_FAILED) {
+        return mErrorCode;
+    }
+
+    status_t status = parcel->writeInt32(mException);
+    if (status != OK) { return status; }
+    if (mException == EX_NONE) {
+        // We have no more information to write.
+        return status;
+    }
+    status = parcel->writeString16(String16(mMessage));
+    if (mException != EX_SERVICE_SPECIFIC) {
+        // We have no more information to write.
+        return status;
+    }
+    status = parcel->writeInt32(mErrorCode);
+    return status;
+}
+
+void Status::setException(int32_t ex, const String8& message) {
+    mException = ex;
+    mErrorCode = NO_ERROR;  // an exception, not a transaction failure.
+    mMessage.setTo(message);
+}
+
+void Status::setServiceSpecificError(int32_t errorCode, const String8& message) {
+    setException(EX_SERVICE_SPECIFIC, message);
+    mErrorCode = errorCode;
+}
+
+void Status::setFromStatusT(status_t status) {
+    mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
+    mErrorCode = status;
+    mMessage.clear();
+}
+
+String8 Status::toString8() const {
+    String8 ret;
+    if (mException == EX_NONE) {
+        ret.append("No error");
+    } else {
+        ret.appendFormat("Status(%d): '", mException);
+        if (mException == EX_SERVICE_SPECIFIC ||
+            mException == EX_TRANSACTION_FAILED) {
+            ret.appendFormat("%d: ", mErrorCode);
+        }
+        ret.append(String8(mMessage));
+        ret.append("'");
+    }
+    return ret;
+}
+
+}  // namespace binder
+}  // namespace android
diff --git a/libs/binder/tests/Android.mk b/libs/binder/tests/Android.mk
index 3668729..a40523d 100644
--- a/libs/binder/tests/Android.mk
+++ b/libs/binder/tests/Android.mk
@@ -32,3 +32,11 @@
 LOCAL_SRC_FILES := binderLibTest.cpp
 LOCAL_SHARED_LIBRARIES := libbinder libutils
 include $(BUILD_NATIVE_TEST)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := binderThroughputTest
+LOCAL_SRC_FILES := binderThroughputTest.cpp
+LOCAL_SHARED_LIBRARIES := libbinder libutils
+LOCAL_CLANG := true
+LOCAL_CFLAGS += -g -Wall -Werror -std=c++11 -Wno-missing-field-initializers -Wno-sign-compare -O3
+include $(BUILD_NATIVE_TEST)
diff --git a/libs/binder/tests/binderDriverInterfaceTest.cpp b/libs/binder/tests/binderDriverInterfaceTest.cpp
index 315f349..0277550 100644
--- a/libs/binder/tests/binderDriverInterfaceTest.cpp
+++ b/libs/binder/tests/binderDriverInterfaceTest.cpp
@@ -34,7 +34,7 @@
             int ret;
             uint32_t max_threads = 0;
 
-            m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK);
+            m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
             ASSERT_GE(m_binderFd, 0);
             m_buffer = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0);
             ASSERT_NE(m_buffer, (void *)NULL);
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
new file mode 100644
index 0000000..71b96d4
--- /dev/null
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -0,0 +1,317 @@
+#include <binder/Binder.h>
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <string>
+#include <cstring>
+#include <cstdlib>
+#include <cstdio>
+
+#include <iostream>
+#include <vector>
+#include <tuple>
+
+#include <unistd.h>
+#include <sys/wait.h>
+
+using namespace std;
+using namespace android;
+
+enum BinderWorkerServiceCode {
+    BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+#define ASSERT_TRUE(cond) \
+do { \
+    if (!(cond)) {\
+       cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \
+       exit(EXIT_FAILURE); \
+    } \
+} while (0)
+
+class BinderWorkerService : public BBinder
+{
+public:
+    BinderWorkerService() {}
+    ~BinderWorkerService() {}
+    virtual status_t onTransact(uint32_t code,
+                                const Parcel& data, Parcel* reply,
+                                uint32_t flags = 0) {
+        (void)flags;
+        (void)data;
+        (void)reply;
+        switch (code) {
+        case BINDER_NOP:
+            return NO_ERROR;
+        default:
+            return UNKNOWN_TRANSACTION;
+        };
+    }
+};
+
+class Pipe {
+    int m_readFd;
+    int m_writeFd;
+    Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {}
+    Pipe(const Pipe &) = delete;
+    Pipe& operator=(const Pipe &) = delete;
+    Pipe& operator=(const Pipe &&) = delete;
+public:
+    Pipe(Pipe&& rval) noexcept {
+        m_readFd = rval.m_readFd;
+        m_writeFd = rval.m_writeFd;
+        rval.m_readFd = 0;
+        rval.m_writeFd = 0;
+    }
+    ~Pipe() {
+        if (m_readFd)
+            close(m_readFd);
+        if (m_writeFd)
+            close(m_writeFd);
+    }
+    void signal() {
+        bool val = true;
+        int error = write(m_writeFd, &val, sizeof(val));
+        ASSERT_TRUE(error >= 0);
+    };
+    void wait() {
+        bool val = false;
+        int error = read(m_readFd, &val, sizeof(val));
+        ASSERT_TRUE(error >= 0);
+    }
+    template <typename T> void send(const T& v) {
+        int error = write(m_writeFd, &v, sizeof(T));
+        ASSERT_TRUE(error >= 0);
+    }
+    template <typename T> void recv(T& v) {
+        int error = read(m_readFd, &v, sizeof(T));
+        ASSERT_TRUE(error >= 0);
+    }
+    static tuple<Pipe, Pipe> createPipePair() {
+        int a[2];
+        int b[2];
+
+        int error1 = pipe(a);
+        int error2 = pipe(b);
+        ASSERT_TRUE(error1 >= 0);
+        ASSERT_TRUE(error2 >= 0);
+
+        return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
+    }
+};
+
+static const uint32_t num_buckets = 128;
+static const uint64_t max_time_bucket = 50ull * 1000000;
+static const uint64_t time_per_bucket = max_time_bucket / num_buckets;
+static constexpr float time_per_bucket_ms = time_per_bucket / 1.0E6;
+
+struct ProcResults {
+    uint64_t m_best = max_time_bucket;
+    uint64_t m_worst = 0;
+    uint32_t m_buckets[num_buckets] = {0};
+    uint64_t m_transactions = 0;
+    uint64_t m_total_time = 0;
+
+    void add_time(uint64_t time) {
+        m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1;
+        m_best = min(time, m_best);
+        m_worst = max(time, m_worst);
+        m_transactions += 1;
+        m_total_time += time;
+    }
+    static ProcResults combine(const ProcResults& a, const ProcResults& b) {
+        ProcResults ret;
+        for (int i = 0; i < num_buckets; i++) {
+            ret.m_buckets[i] = a.m_buckets[i] + b.m_buckets[i];
+        }
+        ret.m_worst = max(a.m_worst, b.m_worst);
+        ret.m_best = min(a.m_best, b.m_best);
+        ret.m_transactions = a.m_transactions + b.m_transactions;
+        ret.m_total_time = a.m_total_time + b.m_total_time;
+        return ret;
+    }
+    void dump() {
+        double best = (double)m_best / 1.0E6;
+        double worst = (double)m_worst / 1.0E6;
+        double average = (double)m_total_time / m_transactions / 1.0E6;
+        cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl;
+
+        uint64_t cur_total = 0;
+        for (int i = 0; i < num_buckets; i++) {
+            float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms;
+            if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) {
+                cout << "50%: " << cur_time << " ";
+            }
+            if ((cur_total < 0.9f * m_transactions) && (cur_total + m_buckets[i] >= 0.9f * m_transactions)) {
+                cout << "90%: " << cur_time << " ";
+            }
+            if ((cur_total < 0.95f * m_transactions) && (cur_total + m_buckets[i] >= 0.95f * m_transactions)) {
+                cout << "95%: " << cur_time << " ";
+            }
+            if ((cur_total < 0.99f * m_transactions) && (cur_total + m_buckets[i] >= 0.99f * m_transactions)) {
+                cout << "99%: " << cur_time << " ";
+            }
+            cur_total += m_buckets[i];
+        }
+        cout << endl;
+
+    }
+};
+
+String16 generateServiceName(int num)
+{
+    char num_str[32];
+    snprintf(num_str, sizeof(num_str), "%d", num);
+    String16 serviceName = String16("binderWorker") + String16(num_str);
+    return serviceName;
+}
+
+void worker_fx(
+    int num,
+    int worker_count,
+    int iterations,
+    Pipe p)
+{
+    // Create BinderWorkerService and for go.
+    ProcessState::self()->startThreadPool();
+    sp<IServiceManager> serviceMgr = defaultServiceManager();
+    sp<BinderWorkerService> service = new BinderWorkerService;
+    serviceMgr->addService(generateServiceName(num), service);
+
+    srand(num);
+    p.signal();
+    p.wait();
+
+    // Get references to other binder services.
+    cout << "Created BinderWorker" << num << endl;
+    (void)worker_count;
+    vector<sp<IBinder> > workers;
+    for (int i = 0; i < worker_count; i++) {
+        if (num == i)
+            continue;
+        workers.push_back(serviceMgr->getService(generateServiceName(i)));
+    }
+
+    // Run the benchmark.
+    ProcResults results;
+    chrono::time_point<chrono::high_resolution_clock> start, end;
+    for (int i = 0; i < iterations; i++) {
+        int target = rand() % workers.size();
+        Parcel data, reply;
+        start = chrono::high_resolution_clock::now();
+        status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
+        end = chrono::high_resolution_clock::now();
+
+        uint64_t cur_time = uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - start).count());
+        results.add_time(cur_time);
+
+        if (ret != NO_ERROR) {
+           cout << "thread " << num << " failed " << ret << "i : " << i << endl;
+           exit(EXIT_FAILURE);
+        }
+    }
+    // Signal completion to master and wait.
+    p.signal();
+    p.wait();
+
+    // Send results to master and wait for go to exit.
+    p.send(results);
+    p.wait();
+
+    exit(EXIT_SUCCESS);
+}
+
+Pipe make_worker(int num, int iterations, int worker_count)
+{
+    auto pipe_pair = Pipe::createPipePair();
+    pid_t pid = fork();
+    if (pid) {
+        /* parent */
+        return move(get<0>(pipe_pair));
+    } else {
+        /* child */
+        worker_fx(num, worker_count, iterations, move(get<1>(pipe_pair)));
+        /* never get here */
+        return move(get<0>(pipe_pair));
+    }
+
+}
+
+void wait_all(vector<Pipe>& v)
+{
+    for (int i = 0; i < v.size(); i++) {
+        v[i].wait();
+    }
+}
+
+void signal_all(vector<Pipe>& v)
+{
+    for (int i = 0; i < v.size(); i++) {
+        v[i].signal();
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int workers = 2;
+    int iterations = 10000;
+    (void)argc;
+    (void)argv;
+    vector<Pipe> pipes;
+
+    // Parse arguments.
+    for (int i = 1; i < argc; i++) {
+        if (string(argv[i]) == "-w") {
+            workers = atoi(argv[i+1]);
+            i++;
+            continue;
+        }
+        if (string(argv[i]) == "-i") {
+            iterations = atoi(argv[i+1]);
+            i++;
+            continue;
+        }
+    }
+
+    // Create all the workers and wait for them to spawn.
+    for (int i = 0; i < workers; i++) {
+        pipes.push_back(make_worker(i, iterations, workers));
+    }
+    wait_all(pipes);
+
+
+    // Run the workers and wait for completion.
+    chrono::time_point<chrono::high_resolution_clock> start, end;
+    cout << "waiting for workers to complete" << endl;
+    start = chrono::high_resolution_clock::now();
+    signal_all(pipes);
+    wait_all(pipes);
+    end = chrono::high_resolution_clock::now();
+
+    // Calculate overall throughput.
+    double iterations_per_sec = double(iterations * workers) / (chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1.0E9);
+    cout << "iterations per sec: " << iterations_per_sec << endl;
+
+    // Collect all results from the workers.
+    cout << "collecting results" << endl;
+    signal_all(pipes);
+    ProcResults tot_results;
+    for (int i = 0; i < workers; i++) {
+        ProcResults tmp_results;
+        pipes[i].recv(tmp_results);
+        tot_results = ProcResults::combine(tot_results, tmp_results);
+    }
+    tot_results.dump();
+
+    // Kill all the workers.
+    cout << "killing workers" << endl;
+    signal_all(pipes);
+    for (int i = 0; i < workers; i++) {
+        int status;
+        wait(&status);
+        if (status != 0) {
+            cout << "nonzero child status" << status << endl;
+        }
+    }
+    return 0;
+}
diff --git a/libs/diskusage/dirsize.c b/libs/diskusage/dirsize.c
index 7576994..5b5ab70 100644
--- a/libs/diskusage/dirsize.c
+++ b/libs/diskusage/dirsize.c
@@ -24,16 +24,7 @@
 
 int64_t stat_size(struct stat *s)
 {
-    int64_t blksize = s->st_blksize;
-    // count actual blocks used instead of nominal file size
-    int64_t size = s->st_blocks * 512;
-
-    if (blksize) {
-        /* round up to filesystem block size */
-        size = (size + blksize - 1) & (~(blksize - 1));
-    }
-
-    return size;
+    return s->st_blocks * 512;
 }
 
 int64_t calculate_dir_size(int dfd)
@@ -51,9 +42,6 @@
 
     while ((de = readdir(d))) {
         const char *name = de->d_name;
-        if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
-            size += stat_size(&s);
-        }
         if (de->d_type == DT_DIR) {
             int subfd;
 
@@ -65,10 +53,17 @@
                     continue;
             }
 
+            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+                size += stat_size(&s);
+            }
             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
             if (subfd >= 0) {
                 size += calculate_dir_size(subfd);
             }
+        } else {
+            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
+                size += stat_size(&s);
+            }
         }
     }
     closedir(d);
diff --git a/libs/gui/Android.mk b/libs/gui/Android.mk
index 8a965dd..6e92a47 100644
--- a/libs/gui/Android.mk
+++ b/libs/gui/Android.mk
@@ -36,6 +36,8 @@
 # Don't warn about struct padding
 LOCAL_CPPFLAGS += -Wno-padded
 
+LOCAL_CPPFLAGS += -DDEBUG_ONLY_CODE=$(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),1,0)
+
 LOCAL_SRC_FILES := \
 	IGraphicBufferConsumer.cpp \
 	IConsumerListener.cpp \
@@ -91,6 +93,12 @@
 	LOCAL_CFLAGS += -DDONT_USE_FENCE_SYNC
 endif
 
+ifeq ($(BOARD_ENABLE_GPU_PROTECTED_CONTENT),true)
+	LOCAL_CFLAGS += -DENABLE_GPU_PROTECTED_CONTENT=true
+else
+	LOCAL_CFLAGS += -DENABLE_GPU_PROTECTED_CONTENT=false
+endif
+
 include $(BUILD_SHARED_LIBRARY)
 
 ifeq (,$(ONE_SHOT_MAKEFILE))
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 8f64ae0..5e3924a 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -24,6 +24,9 @@
 namespace android {
 
 BufferItem::BufferItem() :
+    mGraphicBuffer(NULL),
+    mFence(NULL),
+    mCrop(Rect::INVALID_RECT),
     mTransform(0),
     mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mTimestamp(0),
@@ -33,8 +36,11 @@
     mSlot(INVALID_BUFFER_SLOT),
     mIsDroppable(false),
     mAcquireCalled(false),
-    mTransformToDisplayInverse(false) {
-    mCrop.makeInvalid();
+    mTransformToDisplayInverse(false),
+    mSurfaceDamage(),
+    mAutoRefresh(false),
+    mQueuedBuffer(true),
+    mIsStale(false) {
 }
 
 BufferItem::~BufferItem() {}
diff --git a/libs/gui/BufferItemConsumer.cpp b/libs/gui/BufferItemConsumer.cpp
index 578b8d9..3491043 100644
--- a/libs/gui/BufferItemConsumer.cpp
+++ b/libs/gui/BufferItemConsumer.cpp
@@ -49,6 +49,10 @@
 
 void BufferItemConsumer::setName(const String8& name) {
     Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        BI_LOGE("setName: BufferItemConsumer is abandoned!");
+        return;
+    }
     mName = name;
     mConsumer->setConsumerName(name);
 }
@@ -78,7 +82,7 @@
         }
     }
 
-    item->mGraphicBuffer = mSlots[item->mBuf].mGraphicBuffer;
+    item->mGraphicBuffer = mSlots[item->mSlot].mGraphicBuffer;
 
     return OK;
 }
@@ -89,9 +93,9 @@
 
     Mutex::Autolock _l(mMutex);
 
-    err = addReleaseFenceLocked(item.mBuf, item.mGraphicBuffer, releaseFence);
+    err = addReleaseFenceLocked(item.mSlot, item.mGraphicBuffer, releaseFence);
 
-    err = releaseBufferLocked(item.mBuf, item.mGraphicBuffer, EGL_NO_DISPLAY,
+    err = releaseBufferLocked(item.mSlot, item.mGraphicBuffer, EGL_NO_DISPLAY,
             EGL_NO_SYNC_KHR);
     if (err != OK) {
         BI_LOGE("Failed to release buffer: %s (%d)",
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index 7504ed4..cbc8893 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -20,6 +20,12 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
+#if DEBUG_ONLY_CODE
+#define VALIDATE_CONSISTENCY() do { mCore->validateConsistencyLocked(); } while (0)
+#else
+#define VALIDATE_CONSISTENCY()
+#endif
+
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueConsumer.h>
 #include <gui/BufferQueueCore.h>
@@ -53,8 +59,8 @@
         // buffer so that the consumer can successfully set up the newly acquired
         // buffer before releasing the old one.
         int numAcquiredBuffers = 0;
-        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-            if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
+        for (int s : mCore->mActiveBuffers) {
+            if (mSlots[s].mBufferState.isAcquired()) {
                 ++numAcquiredBuffers;
             }
         }
@@ -64,10 +70,13 @@
             return INVALID_OPERATION;
         }
 
-        // Check if the queue is empty.
+        bool sharedBufferAvailable = mCore->mSharedBufferMode &&
+                mCore->mAutoRefresh && mCore->mSharedBufferSlot !=
+                BufferQueueCore::INVALID_BUFFER_SLOT;
+
         // In asynchronous mode the list is guaranteed to be one buffer deep,
         // while in synchronous mode we use the oldest buffer.
-        if (mCore->mQueue.empty()) {
+        if (mCore->mQueue.empty() && !sharedBufferAvailable) {
             return NO_BUFFER_AVAILABLE;
         }
 
@@ -76,7 +85,9 @@
         // If expectedPresent is specified, we may not want to return a buffer yet.
         // If it's specified and there's more than one buffer queued, we may want
         // to drop a buffer.
-        if (expectedPresent != 0) {
+        // Skip this if we're in shared buffer mode and the queue is empty,
+        // since in that case we'll just return the shared buffer.
+        if (expectedPresent != 0 && !mCore->mQueue.empty()) {
             const int MAX_REASONABLE_NSEC = 1000000000ULL; // 1 second
 
             // The 'expectedPresent' argument indicates when the buffer is expected
@@ -132,13 +143,29 @@
                 BQ_LOGV("acquireBuffer: drop desire=%" PRId64 " expect=%" PRId64
                         " size=%zu",
                         desiredPresent, expectedPresent, mCore->mQueue.size());
-                if (mCore->stillTracking(front)) {
+
+                if (!front->mIsStale) {
                     // Front buffer is still in mSlots, so mark the slot as free
-                    mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
-                    mCore->mFreeBuffers.push_back(front->mSlot);
+                    mSlots[front->mSlot].mBufferState.freeQueued();
+
+                    // After leaving shared buffer mode, the shared buffer will
+                    // still be around. Mark it as no longer shared if this
+                    // operation causes it to be free.
+                    if (!mCore->mSharedBufferMode &&
+                            mSlots[front->mSlot].mBufferState.isFree()) {
+                        mSlots[front->mSlot].mBufferState.mShared = false;
+                    }
+
+                    // Don't put the shared buffer on the free list
+                    if (!mSlots[front->mSlot].mBufferState.isShared()) {
+                        mCore->mActiveBuffers.erase(front->mSlot);
+                        mCore->mFreeBuffers.push_back(front->mSlot);
+                    }
+
                     listener = mCore->mConnectedProducerListener;
                     ++numDroppedBuffers;
                 }
+
                 mCore->mQueue.erase(front);
                 front = mCore->mQueue.begin();
             }
@@ -166,17 +193,55 @@
                     systemTime(CLOCK_MONOTONIC));
         }
 
-        int slot = front->mSlot;
-        *outBuffer = *front;
+        int slot = BufferQueueCore::INVALID_BUFFER_SLOT;
+
+        if (sharedBufferAvailable && mCore->mQueue.empty()) {
+            // make sure the buffer has finished allocating before acquiring it
+            mCore->waitWhileAllocatingLocked();
+
+            slot = mCore->mSharedBufferSlot;
+
+            // Recreate the BufferItem for the shared buffer from the data that
+            // was cached when it was last queued.
+            outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
+            outBuffer->mFence = Fence::NO_FENCE;
+            outBuffer->mCrop = mCore->mSharedBufferCache.crop;
+            outBuffer->mTransform = mCore->mSharedBufferCache.transform &
+                    ~static_cast<uint32_t>(
+                    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY);
+            outBuffer->mScalingMode = mCore->mSharedBufferCache.scalingMode;
+            outBuffer->mDataSpace = mCore->mSharedBufferCache.dataspace;
+            outBuffer->mFrameNumber = mCore->mFrameCounter;
+            outBuffer->mSlot = slot;
+            outBuffer->mAcquireCalled = mSlots[slot].mAcquireCalled;
+            outBuffer->mTransformToDisplayInverse =
+                    (mCore->mSharedBufferCache.transform &
+                    NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) != 0;
+            outBuffer->mSurfaceDamage = Region::INVALID_REGION;
+            outBuffer->mQueuedBuffer = false;
+            outBuffer->mIsStale = false;
+            outBuffer->mAutoRefresh = mCore->mSharedBufferMode &&
+                    mCore->mAutoRefresh;
+        } else {
+            slot = front->mSlot;
+            *outBuffer = *front;
+        }
+
         ATRACE_BUFFER_INDEX(slot);
 
         BQ_LOGV("acquireBuffer: acquiring { slot=%d/%" PRIu64 " buffer=%p }",
-                slot, front->mFrameNumber, front->mGraphicBuffer->handle);
-        // If the front buffer is still being tracked, update its slot state
-        if (mCore->stillTracking(front)) {
+                slot, outBuffer->mFrameNumber, outBuffer->mGraphicBuffer->handle);
+
+        if (!outBuffer->mIsStale) {
             mSlots[slot].mAcquireCalled = true;
-            mSlots[slot].mNeedsCleanupOnRelease = false;
-            mSlots[slot].mBufferState = BufferSlot::ACQUIRED;
+            // Don't decrease the queue count if the BufferItem wasn't
+            // previously in the queue. This happens in shared buffer mode when
+            // the queue is empty and the BufferItem is created above.
+            if (mCore->mQueue.empty()) {
+                mSlots[slot].mBufferState.acquireNotInQueue();
+            } else {
+                mSlots[slot].mBufferState.acquire();
+            }
             mSlots[slot].mFence = Fence::NO_FENCE;
         }
 
@@ -196,7 +261,7 @@
 
         ATRACE_INT(mCore->mConsumerName.string(), mCore->mQueue.size());
 
-        mCore->validateConsistencyLocked();
+        VALIDATE_CONSISTENCY();
     }
 
     if (listener != NULL) {
@@ -211,27 +276,35 @@
 status_t BufferQueueConsumer::detachBuffer(int slot) {
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(slot);
-    BQ_LOGV("detachBuffer(C): slot %d", slot);
+    BQ_LOGV("detachBuffer: slot %d", slot);
     Mutex::Autolock lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
-        BQ_LOGE("detachBuffer(C): BufferQueue has been abandoned");
+        BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
         return NO_INIT;
     }
 
-    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
-        BQ_LOGE("detachBuffer(C): slot index %d out of range [0, %d)",
-                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
-        return BAD_VALUE;
-    } else if (mSlots[slot].mBufferState != BufferSlot::ACQUIRED) {
-        BQ_LOGE("detachBuffer(C): slot %d is not owned by the consumer "
-                "(state = %d)", slot, mSlots[slot].mBufferState);
+    if (mCore->mSharedBufferMode || slot == mCore->mSharedBufferSlot) {
+        BQ_LOGE("detachBuffer: detachBuffer not allowed in shared buffer mode");
         return BAD_VALUE;
     }
 
-    mCore->freeBufferLocked(slot);
+    if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
+        BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
+                slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
+        return BAD_VALUE;
+    } else if (!mSlots[slot].mBufferState.isAcquired()) {
+        BQ_LOGE("detachBuffer: slot %d is not owned by the consumer "
+                "(state = %s)", slot, mSlots[slot].mBufferState.string());
+        return BAD_VALUE;
+    }
+
+    mSlots[slot].mBufferState.detachConsumer();
+    mCore->mActiveBuffers.erase(slot);
+    mCore->mFreeSlots.insert(slot);
+    mCore->clearBufferSlotLocked(slot);
     mCore->mDequeueCondition.broadcast();
-    mCore->validateConsistencyLocked();
+    VALIDATE_CONSISTENCY();
 
     return NO_ERROR;
 }
@@ -241,25 +314,30 @@
     ATRACE_CALL();
 
     if (outSlot == NULL) {
-        BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
+        BQ_LOGE("attachBuffer: outSlot must not be NULL");
         return BAD_VALUE;
     } else if (buffer == NULL) {
-        BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
+        BQ_LOGE("attachBuffer: cannot attach NULL buffer");
         return BAD_VALUE;
     }
 
     Mutex::Autolock lock(mCore->mMutex);
 
+    if (mCore->mSharedBufferMode) {
+        BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
+        return BAD_VALUE;
+    }
+
     // Make sure we don't have too many acquired buffers
     int numAcquiredBuffers = 0;
-    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-        if (mSlots[s].mBufferState == BufferSlot::ACQUIRED) {
+    for (int s : mCore->mActiveBuffers) {
+        if (mSlots[s].mBufferState.isAcquired()) {
             ++numAcquiredBuffers;
         }
     }
 
     if (numAcquiredBuffers >= mCore->mMaxAcquiredBufferCount + 1) {
-        BQ_LOGE("attachBuffer(P): max acquired buffer count reached: %d "
+        BQ_LOGE("attachBuffer: max acquired buffer count reached: %d "
                 "(max %d)", numAcquiredBuffers,
                 mCore->mMaxAcquiredBufferCount);
         return INVALID_OPERATION;
@@ -283,18 +361,18 @@
         mCore->mFreeBuffers.remove(found);
     }
     if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
-        BQ_LOGE("attachBuffer(P): could not find free buffer slot");
+        BQ_LOGE("attachBuffer: could not find free buffer slot");
         return NO_MEMORY;
     }
 
+    mCore->mActiveBuffers.insert(found);
     *outSlot = found;
     ATRACE_BUFFER_INDEX(*outSlot);
-    BQ_LOGV("attachBuffer(C): returning slot %d", *outSlot);
+    BQ_LOGV("attachBuffer: returning slot %d", *outSlot);
 
     mSlots[*outSlot].mGraphicBuffer = buffer;
-    mSlots[*outSlot].mBufferState = BufferSlot::ACQUIRED;
-    mSlots[*outSlot].mAttachedByConsumer = true;
-    mSlots[*outSlot].mNeedsCleanupOnRelease = false;
+    mSlots[*outSlot].mBufferState.attachConsumer();
+    mSlots[*outSlot].mNeedsReallocation = true;
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
     mSlots[*outSlot].mFrameNumber = 0;
 
@@ -315,7 +393,7 @@
     // for attached buffers.
     mSlots[*outSlot].mAcquireCalled = false;
 
-    mCore->validateConsistencyLocked();
+    VALIDATE_CONSISTENCY();
 
     return NO_ERROR;
 }
@@ -338,43 +416,44 @@
         Mutex::Autolock lock(mCore->mMutex);
 
         // If the frame number has changed because the buffer has been reallocated,
-        // we can ignore this releaseBuffer for the old buffer
-        if (frameNumber != mSlots[slot].mFrameNumber) {
+        // we can ignore this releaseBuffer for the old buffer.
+        // Ignore this for the shared buffer where the frame number can easily
+        // get out of sync due to the buffer being queued and acquired at the
+        // same time.
+        if (frameNumber != mSlots[slot].mFrameNumber &&
+                !mSlots[slot].mBufferState.isShared()) {
             return STALE_BUFFER_SLOT;
         }
 
-        // Make sure this buffer hasn't been queued while acquired by the consumer
-        BufferQueueCore::Fifo::iterator current(mCore->mQueue.begin());
-        while (current != mCore->mQueue.end()) {
-            if (current->mSlot == slot) {
-                BQ_LOGE("releaseBuffer: buffer slot %d pending release is "
-                        "currently queued", slot);
-                return BAD_VALUE;
-            }
-            ++current;
-        }
-
-        if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
-            mSlots[slot].mEglDisplay = eglDisplay;
-            mSlots[slot].mEglFence = eglFence;
-            mSlots[slot].mFence = releaseFence;
-            mSlots[slot].mBufferState = BufferSlot::FREE;
-            mCore->mFreeBuffers.push_back(slot);
-            listener = mCore->mConnectedProducerListener;
-            BQ_LOGV("releaseBuffer: releasing slot %d", slot);
-        } else if (mSlots[slot].mNeedsCleanupOnRelease) {
-            BQ_LOGV("releaseBuffer: releasing a stale buffer slot %d "
-                    "(state = %d)", slot, mSlots[slot].mBufferState);
-            mSlots[slot].mNeedsCleanupOnRelease = false;
-            return STALE_BUFFER_SLOT;
-        } else {
+        if (!mSlots[slot].mBufferState.isAcquired()) {
             BQ_LOGE("releaseBuffer: attempted to release buffer slot %d "
-                    "but its state was %d", slot, mSlots[slot].mBufferState);
+                    "but its state was %s", slot,
+                    mSlots[slot].mBufferState.string());
             return BAD_VALUE;
         }
 
+        mSlots[slot].mEglDisplay = eglDisplay;
+        mSlots[slot].mEglFence = eglFence;
+        mSlots[slot].mFence = releaseFence;
+        mSlots[slot].mBufferState.release();
+
+        // After leaving shared buffer mode, the shared buffer will
+        // still be around. Mark it as no longer shared if this
+        // operation causes it to be free.
+        if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
+            mSlots[slot].mBufferState.mShared = false;
+        }
+        // Don't put the shared buffer on the free list.
+        if (!mSlots[slot].mBufferState.isShared()) {
+            mCore->mActiveBuffers.erase(slot);
+            mCore->mFreeBuffers.push_back(slot);
+        }
+
+        listener = mCore->mConnectedProducerListener;
+        BQ_LOGV("releaseBuffer: releasing slot %d", slot);
+
         mCore->mDequeueCondition.broadcast();
-        mCore->validateConsistencyLocked();
+        VALIDATE_CONSISTENCY();
     } // Autolock scope
 
     // Call back without lock held
@@ -390,17 +469,17 @@
     ATRACE_CALL();
 
     if (consumerListener == NULL) {
-        BQ_LOGE("connect(C): consumerListener may not be NULL");
+        BQ_LOGE("connect: consumerListener may not be NULL");
         return BAD_VALUE;
     }
 
-    BQ_LOGV("connect(C): controlledByApp=%s",
+    BQ_LOGV("connect: controlledByApp=%s",
             controlledByApp ? "true" : "false");
 
     Mutex::Autolock lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
-        BQ_LOGE("connect(C): BufferQueue has been abandoned");
+        BQ_LOGE("connect: BufferQueue has been abandoned");
         return NO_INIT;
     }
 
@@ -413,12 +492,12 @@
 status_t BufferQueueConsumer::disconnect() {
     ATRACE_CALL();
 
-    BQ_LOGV("disconnect(C)");
+    BQ_LOGV("disconnect");
 
     Mutex::Autolock lock(mCore->mMutex);
 
     if (mCore->mConsumerListener == NULL) {
-        BQ_LOGE("disconnect(C): no consumer is connected");
+        BQ_LOGE("disconnect: no consumer is connected");
         return BAD_VALUE;
     }
 
@@ -426,6 +505,7 @@
     mCore->mConsumerListener = NULL;
     mCore->mQueue.clear();
     mCore->freeAllBuffersLocked();
+    mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
     mCore->mDequeueCondition.broadcast();
     return NO_ERROR;
 }
@@ -486,24 +566,38 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueConsumer::setDefaultMaxBufferCount(int bufferCount) {
+status_t BufferQueueConsumer::setMaxBufferCount(int bufferCount) {
     ATRACE_CALL();
-    Mutex::Autolock lock(mCore->mMutex);
-    return mCore->setDefaultMaxBufferCountLocked(bufferCount);
-}
 
-status_t BufferQueueConsumer::disableAsyncBuffer() {
-    ATRACE_CALL();
+    if (bufferCount < 1 || bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+        BQ_LOGE("setMaxBufferCount: invalid count %d", bufferCount);
+        return BAD_VALUE;
+    }
 
     Mutex::Autolock lock(mCore->mMutex);
 
-    if (mCore->mConsumerListener != NULL) {
-        BQ_LOGE("disableAsyncBuffer: consumer already connected");
+    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("setMaxBufferCount: producer is already connected");
         return INVALID_OPERATION;
     }
 
-    BQ_LOGV("disableAsyncBuffer");
-    mCore->mUseAsyncBuffer = false;
+    if (bufferCount < mCore->mMaxAcquiredBufferCount) {
+        BQ_LOGE("setMaxBufferCount: invalid buffer count (%d) less than"
+                "mMaxAcquiredBufferCount (%d)", bufferCount,
+                mCore->mMaxAcquiredBufferCount);
+        return BAD_VALUE;
+    }
+
+    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
+            mCore->mDequeueBufferCannotBlock, bufferCount) -
+            mCore->getMaxBufferCountLocked();
+    if (!mCore->adjustAvailableSlotsLocked(delta)) {
+        BQ_LOGE("setMaxBufferCount: BufferQueue failed to adjust the number of "
+                "available slots. Delta = %d", delta);
+        return BAD_VALUE;
+    }
+
+    mCore->mMaxBufferCount = bufferCount;
     return NO_ERROR;
 }
 
@@ -518,15 +612,63 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock lock(mCore->mMutex);
+    sp<IConsumerListener> listener;
+    { // Autolock scope
+        Mutex::Autolock lock(mCore->mMutex);
+        mCore->waitWhileAllocatingLocked();
 
-    if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
-        BQ_LOGE("setMaxAcquiredBufferCount: producer is already connected");
-        return INVALID_OPERATION;
+        if (mCore->mIsAbandoned) {
+            BQ_LOGE("setMaxAcquiredBufferCount: consumer is abandoned");
+            return NO_INIT;
+        }
+
+        if (maxAcquiredBuffers == mCore->mMaxAcquiredBufferCount) {
+            return NO_ERROR;
+        }
+
+        // The new maxAcquiredBuffers count should not be violated by the number
+        // of currently acquired buffers
+        int acquiredCount = 0;
+        for (int slot : mCore->mActiveBuffers) {
+            if (mSlots[slot].mBufferState.isAcquired()) {
+                acquiredCount++;
+            }
+        }
+        if (acquiredCount > maxAcquiredBuffers) {
+            BQ_LOGE("setMaxAcquiredBufferCount: the requested maxAcquiredBuffer"
+                    "count (%d) exceeds the current acquired buffer count (%d)",
+                    maxAcquiredBuffers, acquiredCount);
+            return BAD_VALUE;
+        }
+
+        if ((maxAcquiredBuffers + mCore->mMaxDequeuedBufferCount +
+                (mCore->mAsyncMode || mCore->mDequeueBufferCannotBlock ? 1 : 0))
+                > mCore->mMaxBufferCount) {
+            BQ_LOGE("setMaxAcquiredBufferCount: %d acquired buffers would "
+                    "exceed the maxBufferCount (%d) (maxDequeued %d async %d)",
+                    maxAcquiredBuffers, mCore->mMaxBufferCount,
+                    mCore->mMaxDequeuedBufferCount, mCore->mAsyncMode ||
+                    mCore->mDequeueBufferCannotBlock);
+            return BAD_VALUE;
+        }
+
+        int delta = maxAcquiredBuffers - mCore->mMaxAcquiredBufferCount;
+        if (!mCore->adjustAvailableSlotsLocked(delta)) {
+            return BAD_VALUE;
+        }
+
+        BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
+        mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
+        VALIDATE_CONSISTENCY();
+        if (delta < 0) {
+            listener = mCore->mConsumerListener;
+        }
+    }
+    // Call back without lock held
+    if (listener != NULL) {
+        listener->onBuffersReleased();
     }
 
-    BQ_LOGV("setMaxAcquiredBufferCount: %d", maxAcquiredBuffers);
-    mCore->mMaxAcquiredBufferCount = maxAcquiredBuffers;
     return NO_ERROR;
 }
 
diff --git a/libs/gui/BufferQueueCore.cpp b/libs/gui/BufferQueueCore.cpp
index 851a396..ba34eb6 100644
--- a/libs/gui/BufferQueueCore.cpp
+++ b/libs/gui/BufferQueueCore.cpp
@@ -20,6 +20,12 @@
 
 #define EGL_EGLEXT_PROTOTYPES
 
+#if DEBUG_ONLY_CODE
+#define VALIDATE_CONSISTENCY() do { validateConsistencyLocked(); } while (0)
+#else
+#define VALIDATE_CONSISTENCY()
+#endif
+
 #include <inttypes.h>
 
 #include <gui/BufferItem.h>
@@ -30,9 +36,6 @@
 #include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 
-template <typename T>
-static inline T max(T a, T b) { return a > b ? a : b; }
-
 namespace android {
 
 static String8 getUniqueName() {
@@ -55,16 +58,17 @@
     mQueue(),
     mFreeSlots(),
     mFreeBuffers(),
-    mOverrideMaxBufferCount(0),
+    mUnusedSlots(),
+    mActiveBuffers(),
     mDequeueCondition(),
-    mUseAsyncBuffer(true),
     mDequeueBufferCannotBlock(false),
     mDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888),
     mDefaultWidth(1),
     mDefaultHeight(1),
     mDefaultBufferDataSpace(HAL_DATASPACE_UNKNOWN),
-    mDefaultMaxBufferCount(2),
+    mMaxBufferCount(BufferQueueDefs::NUM_BUFFER_SLOTS),
     mMaxAcquiredBufferCount(1),
+    mMaxDequeuedBufferCount(1),
     mBufferHasBeenQueued(false),
     mFrameCounter(0),
     mTransformHint(0),
@@ -72,7 +76,13 @@
     mIsAllocatingCondition(),
     mAllowAllocation(true),
     mBufferAge(0),
-    mGenerationNumber(0)
+    mGenerationNumber(0),
+    mAsyncMode(false),
+    mSharedBufferMode(false),
+    mAutoRefresh(false),
+    mSharedBufferSlot(INVALID_BUFFER_SLOT),
+    mSharedBufferCache(Rect::INVALID_RECT, 0, NATIVE_WINDOW_SCALING_MODE_FREEZE,
+            HAL_DATASPACE_UNKNOWN)
 {
     if (allocator == NULL) {
         sp<ISurfaceComposer> composer(ComposerService::getComposerService());
@@ -81,8 +91,14 @@
             BQ_LOGE("createGraphicBufferAlloc failed");
         }
     }
-    for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
-        mFreeSlots.insert(slot);
+
+    int numStartingBuffers = getMaxBufferCountLocked();
+    for (int s = 0; s < numStartingBuffers; s++) {
+        mFreeSlots.insert(s);
+    }
+    for (int s = numStartingBuffers; s < BufferQueueDefs::NUM_BUFFER_SLOTS;
+            s++) {
+        mUnusedSlots.push_front(s);
     }
 }
 
@@ -104,116 +120,85 @@
     }
 
     result.appendFormat("%s-BufferQueue mMaxAcquiredBufferCount=%d, "
-            "mDequeueBufferCannotBlock=%d, default-size=[%dx%d], "
-            "default-format=%d, transform-hint=%02x, FIFO(%zu)={%s}\n",
-            prefix, mMaxAcquiredBufferCount, mDequeueBufferCannotBlock,
-            mDefaultWidth, mDefaultHeight, mDefaultBufferFormat, mTransformHint,
-            mQueue.size(), fifo.string());
+            "mMaxDequeuedBufferCount=%d, mDequeueBufferCannotBlock=%d "
+            "mAsyncMode=%d, default-size=[%dx%d], default-format=%d, "
+            "transform-hint=%02x, FIFO(%zu)={%s}\n", prefix,
+            mMaxAcquiredBufferCount, mMaxDequeuedBufferCount,
+            mDequeueBufferCannotBlock, mAsyncMode, mDefaultWidth,
+            mDefaultHeight, mDefaultBufferFormat, mTransformHint, mQueue.size(),
+            fifo.string());
 
-    // Trim the free buffers so as to not spam the dump
-    int maxBufferCount = 0;
-    for (int s = BufferQueueDefs::NUM_BUFFER_SLOTS - 1; s >= 0; --s) {
-        const BufferSlot& slot(mSlots[s]);
-        if (slot.mBufferState != BufferSlot::FREE ||
-                slot.mGraphicBuffer != NULL) {
-            maxBufferCount = s + 1;
-            break;
+    for (int s : mActiveBuffers) {
+        const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
+        // A dequeued buffer might be null if it's still being allocated
+        if (buffer.get()) {
+            result.appendFormat("%s%s[%02d:%p] state=%-8s, %p "
+                    "[%4ux%4u:%4u,%3X]\n", prefix,
+                    (mSlots[s].mBufferState.isAcquired()) ? ">" : " ", s,
+                    buffer.get(), mSlots[s].mBufferState.string(),
+                    buffer->handle, buffer->width, buffer->height,
+                    buffer->stride, buffer->format);
+        } else {
+            result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+                    buffer.get(), mSlots[s].mBufferState.string());
         }
     }
+    for (int s : mFreeBuffers) {
+        const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
+        result.appendFormat("%s [%02d:%p] state=%-8s, %p [%4ux%4u:%4u,%3X]\n",
+                prefix, s, buffer.get(), mSlots[s].mBufferState.string(),
+                buffer->handle, buffer->width, buffer->height, buffer->stride,
+                buffer->format);
+    }
 
-    for (int s = 0; s < maxBufferCount; ++s) {
-        const BufferSlot& slot(mSlots[s]);
-        const sp<GraphicBuffer>& buffer(slot.mGraphicBuffer);
-        result.appendFormat("%s%s[%02d:%p] state=%-8s", prefix,
-                (slot.mBufferState == BufferSlot::ACQUIRED) ? ">" : " ",
-                s, buffer.get(),
-                BufferSlot::bufferStateName(slot.mBufferState));
-
-        if (buffer != NULL) {
-            result.appendFormat(", %p [%4ux%4u:%4u,%3X]", buffer->handle,
-                    buffer->width, buffer->height, buffer->stride,
-                    buffer->format);
-        }
-
-        result.append("\n");
+    for (int s : mFreeSlots) {
+        const sp<GraphicBuffer>& buffer(mSlots[s].mGraphicBuffer);
+        result.appendFormat("%s [%02d:%p] state=%-8s\n", prefix, s,
+                buffer.get(), mSlots[s].mBufferState.string());
     }
 }
 
-int BufferQueueCore::getMinUndequeuedBufferCountLocked(bool async) const {
+int BufferQueueCore::getMinUndequeuedBufferCountLocked() const {
     // If dequeueBuffer is allowed to error out, we don't have to add an
     // extra buffer.
-    if (!mUseAsyncBuffer) {
-        return mMaxAcquiredBufferCount;
-    }
-
-    if (mDequeueBufferCannotBlock || async) {
+    if (mAsyncMode || mDequeueBufferCannotBlock) {
         return mMaxAcquiredBufferCount + 1;
     }
 
     return mMaxAcquiredBufferCount;
 }
 
-int BufferQueueCore::getMinMaxBufferCountLocked(bool async) const {
-    return getMinUndequeuedBufferCountLocked(async) + 1;
+int BufferQueueCore::getMinMaxBufferCountLocked() const {
+    return getMinUndequeuedBufferCountLocked() + 1;
 }
 
-int BufferQueueCore::getMaxBufferCountLocked(bool async) const {
-    int minMaxBufferCount = getMinMaxBufferCountLocked(async);
+int BufferQueueCore::getMaxBufferCountLocked(bool asyncMode,
+        bool dequeueBufferCannotBlock, int maxBufferCount) const {
+    int maxCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
+            ((asyncMode || dequeueBufferCannotBlock) ? 1 : 0);
+    maxCount = std::min(maxBufferCount, maxCount);
+    return maxCount;
+}
 
-    int maxBufferCount = max(mDefaultMaxBufferCount, minMaxBufferCount);
-    if (mOverrideMaxBufferCount != 0) {
-        assert(mOverrideMaxBufferCount >= minMaxBufferCount);
-        maxBufferCount = mOverrideMaxBufferCount;
-    }
+int BufferQueueCore::getMaxBufferCountLocked() const {
+    int maxBufferCount = mMaxAcquiredBufferCount + mMaxDequeuedBufferCount +
+            ((mAsyncMode || mDequeueBufferCannotBlock) ? 1 : 0);
 
-    // Any buffers that are dequeued by the producer or sitting in the queue
-    // waiting to be consumed need to have their slots preserved. Such buffers
-    // will temporarily keep the max buffer count up until the slots no longer
-    // need to be preserved.
-    for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-        BufferSlot::BufferState state = mSlots[s].mBufferState;
-        if (state == BufferSlot::QUEUED || state == BufferSlot::DEQUEUED) {
-            maxBufferCount = s + 1;
-        }
-    }
+    // limit maxBufferCount by mMaxBufferCount always
+    maxBufferCount = std::min(mMaxBufferCount, maxBufferCount);
 
     return maxBufferCount;
 }
 
-status_t BufferQueueCore::setDefaultMaxBufferCountLocked(int count) {
-    const int minBufferCount = mUseAsyncBuffer ? 2 : 1;
-    if (count < minBufferCount || count > BufferQueueDefs::NUM_BUFFER_SLOTS) {
-        BQ_LOGV("setDefaultMaxBufferCount: invalid count %d, should be in "
-                "[%d, %d]",
-                count, minBufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
-        return BAD_VALUE;
-    }
+void BufferQueueCore::clearBufferSlotLocked(int slot) {
+    BQ_LOGV("clearBufferSlotLocked: slot %d", slot);
 
-    BQ_LOGV("setDefaultMaxBufferCount: setting count to %d", count);
-    mDefaultMaxBufferCount = count;
-    mDequeueCondition.broadcast();
-
-    return NO_ERROR;
-}
-
-void BufferQueueCore::freeBufferLocked(int slot) {
-    BQ_LOGV("freeBufferLocked: slot %d", slot);
-    bool hadBuffer = mSlots[slot].mGraphicBuffer != NULL;
     mSlots[slot].mGraphicBuffer.clear();
-    if (mSlots[slot].mBufferState == BufferSlot::ACQUIRED) {
-        mSlots[slot].mNeedsCleanupOnRelease = true;
-    }
-    if (mSlots[slot].mBufferState != BufferSlot::FREE) {
-        mFreeSlots.insert(slot);
-    } else if (hadBuffer) {
-        // If the slot was FREE, but we had a buffer, we need to move this slot
-        // from the free buffers list to the the free slots list
-        mFreeBuffers.remove(slot);
-        mFreeSlots.insert(slot);
-    }
-    mSlots[slot].mBufferState = BufferSlot::FREE;
-    mSlots[slot].mAcquireCalled = false;
+    mSlots[slot].mBufferState.reset();
+    mSlots[slot].mRequestBufferCalled = false;
     mSlots[slot].mFrameNumber = 0;
+    mSlots[slot].mAcquireCalled = false;
+    mSlots[slot].mNeedsReallocation = true;
 
     // Destroy fence as BufferQueue now takes ownership
     if (mSlots[slot].mEglFence != EGL_NO_SYNC_KHR) {
@@ -221,30 +206,76 @@
         mSlots[slot].mEglFence = EGL_NO_SYNC_KHR;
     }
     mSlots[slot].mFence = Fence::NO_FENCE;
-    validateConsistencyLocked();
-}
+    mSlots[slot].mEglDisplay = EGL_NO_DISPLAY;
 
-void BufferQueueCore::freeAllBuffersLocked() {
-    mBufferHasBeenQueued = false;
-    for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-        freeBufferLocked(s);
+    if (mLastQueuedSlot == slot) {
+        mLastQueuedSlot = INVALID_BUFFER_SLOT;
     }
 }
 
-bool BufferQueueCore::stillTracking(const BufferItem* item) const {
-    const BufferSlot& slot = mSlots[item->mSlot];
+void BufferQueueCore::freeAllBuffersLocked() {
+    for (int s : mFreeSlots) {
+        clearBufferSlotLocked(s);
+    }
 
-    BQ_LOGV("stillTracking: item { slot=%d/%" PRIu64 " buffer=%p } "
-            "slot { slot=%d/%" PRIu64 " buffer=%p }",
-            item->mSlot, item->mFrameNumber,
-            (item->mGraphicBuffer.get() ? item->mGraphicBuffer->handle : 0),
-            item->mSlot, slot.mFrameNumber,
-            (slot.mGraphicBuffer.get() ? slot.mGraphicBuffer->handle : 0));
+    for (int s : mFreeBuffers) {
+        mFreeSlots.insert(s);
+        clearBufferSlotLocked(s);
+    }
+    mFreeBuffers.clear();
 
-    // Compare item with its original buffer slot. We can check the slot as
-    // the buffer would not be moved to a different slot by the producer.
-    return (slot.mGraphicBuffer != NULL) &&
-           (item->mGraphicBuffer->handle == slot.mGraphicBuffer->handle);
+    for (int s : mActiveBuffers) {
+        mFreeSlots.insert(s);
+        clearBufferSlotLocked(s);
+    }
+    mActiveBuffers.clear();
+
+    for (auto& b : mQueue) {
+        b.mIsStale = true;
+    }
+
+    VALIDATE_CONSISTENCY();
+}
+
+bool BufferQueueCore::adjustAvailableSlotsLocked(int delta) {
+    if (delta >= 0) {
+        // If we're going to fail, do so before modifying anything
+        if (delta > static_cast<int>(mUnusedSlots.size())) {
+            return false;
+        }
+        while (delta > 0) {
+            if (mUnusedSlots.empty()) {
+                return false;
+            }
+            int slot = mUnusedSlots.back();
+            mUnusedSlots.pop_back();
+            mFreeSlots.insert(slot);
+            delta--;
+        }
+    } else {
+        // If we're going to fail, do so before modifying anything
+        if (-delta > static_cast<int>(mFreeSlots.size() +
+                mFreeBuffers.size())) {
+            return false;
+        }
+        while (delta < 0) {
+            if (!mFreeSlots.empty()) {
+                auto slot = mFreeSlots.begin();
+                clearBufferSlotLocked(*slot);
+                mUnusedSlots.push_back(*slot);
+                mFreeSlots.erase(slot);
+            } else if (!mFreeBuffers.empty()) {
+                int slot = mFreeBuffers.back();
+                clearBufferSlotLocked(slot);
+                mUnusedSlots.push_back(slot);
+                mFreeBuffers.pop_back();
+            } else {
+                return false;
+            }
+            delta++;
+        }
+    }
+    return true;
 }
 
 void BufferQueueCore::waitWhileAllocatingLocked() const {
@@ -254,48 +285,131 @@
     }
 }
 
+#if DEBUG_ONLY_CODE
 void BufferQueueCore::validateConsistencyLocked() const {
     static const useconds_t PAUSE_TIME = 0;
+    int allocatedSlots = 0;
     for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
         bool isInFreeSlots = mFreeSlots.count(slot) != 0;
         bool isInFreeBuffers =
                 std::find(mFreeBuffers.cbegin(), mFreeBuffers.cend(), slot) !=
                 mFreeBuffers.cend();
-        if (mSlots[slot].mBufferState == BufferSlot::FREE) {
-            if (mSlots[slot].mGraphicBuffer == NULL) {
-                if (!isInFreeSlots) {
-                    BQ_LOGE("Slot %d is FREE but is not in mFreeSlots", slot);
-                    usleep(PAUSE_TIME);
-                }
-                if (isInFreeBuffers) {
-                    BQ_LOGE("Slot %d is in mFreeSlots "
-                            "but is also in mFreeBuffers", slot);
-                    usleep(PAUSE_TIME);
-                }
-            } else {
-                if (!isInFreeBuffers) {
-                    BQ_LOGE("Slot %d is FREE but is not in mFreeBuffers", slot);
-                    usleep(PAUSE_TIME);
-                }
-                if (isInFreeSlots) {
-                    BQ_LOGE("Slot %d is in mFreeBuffers "
-                            "but is also in mFreeSlots", slot);
-                    usleep(PAUSE_TIME);
-                }
-            }
-        } else {
+        bool isInActiveBuffers = mActiveBuffers.count(slot) != 0;
+        bool isInUnusedSlots =
+                std::find(mUnusedSlots.cbegin(), mUnusedSlots.cend(), slot) !=
+                mUnusedSlots.cend();
+
+        if (isInFreeSlots || isInFreeBuffers || isInActiveBuffers) {
+            allocatedSlots++;
+        }
+
+        if (isInUnusedSlots) {
             if (isInFreeSlots) {
-                BQ_LOGE("Slot %d is in mFreeSlots but is not FREE (%d)",
-                        slot, mSlots[slot].mBufferState);
+                BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeSlots", slot);
                 usleep(PAUSE_TIME);
             }
             if (isInFreeBuffers) {
-                BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE (%d)",
-                        slot, mSlots[slot].mBufferState);
+                BQ_LOGE("Slot %d is in mUnusedSlots and in mFreeBuffers", slot);
                 usleep(PAUSE_TIME);
             }
+            if (isInActiveBuffers) {
+                BQ_LOGE("Slot %d is in mUnusedSlots and in mActiveBuffers",
+                        slot);
+                usleep(PAUSE_TIME);
+            }
+            if (!mSlots[slot].mBufferState.isFree()) {
+                BQ_LOGE("Slot %d is in mUnusedSlots but is not FREE", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (mSlots[slot].mGraphicBuffer != NULL) {
+                BQ_LOGE("Slot %d is in mUnusedSluts but has an active buffer",
+                        slot);
+                usleep(PAUSE_TIME);
+            }
+        } else if (isInFreeSlots) {
+            if (isInUnusedSlots) {
+                BQ_LOGE("Slot %d is in mFreeSlots and in mUnusedSlots", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (isInFreeBuffers) {
+                BQ_LOGE("Slot %d is in mFreeSlots and in mFreeBuffers", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (isInActiveBuffers) {
+                BQ_LOGE("Slot %d is in mFreeSlots and in mActiveBuffers", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (!mSlots[slot].mBufferState.isFree()) {
+                BQ_LOGE("Slot %d is in mFreeSlots but is not FREE", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (mSlots[slot].mGraphicBuffer != NULL) {
+                BQ_LOGE("Slot %d is in mFreeSlots but has a buffer",
+                        slot);
+                usleep(PAUSE_TIME);
+            }
+        } else if (isInFreeBuffers) {
+            if (isInUnusedSlots) {
+                BQ_LOGE("Slot %d is in mFreeBuffers and in mUnusedSlots", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (isInFreeSlots) {
+                BQ_LOGE("Slot %d is in mFreeBuffers and in mFreeSlots", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (isInActiveBuffers) {
+                BQ_LOGE("Slot %d is in mFreeBuffers and in mActiveBuffers",
+                        slot);
+                usleep(PAUSE_TIME);
+            }
+            if (!mSlots[slot].mBufferState.isFree()) {
+                BQ_LOGE("Slot %d is in mFreeBuffers but is not FREE", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (mSlots[slot].mGraphicBuffer == NULL) {
+                BQ_LOGE("Slot %d is in mFreeBuffers but has no buffer", slot);
+                usleep(PAUSE_TIME);
+            }
+        } else if (isInActiveBuffers) {
+            if (isInUnusedSlots) {
+                BQ_LOGE("Slot %d is in mActiveBuffers and in mUnusedSlots",
+                        slot);
+                usleep(PAUSE_TIME);
+            }
+            if (isInFreeSlots) {
+                BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeSlots", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (isInFreeBuffers) {
+                BQ_LOGE("Slot %d is in mActiveBuffers and in mFreeBuffers",
+                        slot);
+                usleep(PAUSE_TIME);
+            }
+            if (mSlots[slot].mBufferState.isFree() &&
+                    !mSlots[slot].mBufferState.isShared()) {
+                BQ_LOGE("Slot %d is in mActiveBuffers but is FREE", slot);
+                usleep(PAUSE_TIME);
+            }
+            if (mSlots[slot].mGraphicBuffer == NULL && !mIsAllocating) {
+                BQ_LOGE("Slot %d is in mActiveBuffers but has no buffer", slot);
+                usleep(PAUSE_TIME);
+            }
+        } else {
+            BQ_LOGE("Slot %d isn't in any of mUnusedSlots, mFreeSlots, "
+                    "mFreeBuffers, or mActiveBuffers", slot);
+            usleep(PAUSE_TIME);
         }
     }
+
+    if (allocatedSlots != getMaxBufferCountLocked()) {
+        BQ_LOGE("Number of allocated slots is incorrect. Allocated = %d, "
+                "Should be %d (%zu free slots, %zu free buffers, "
+                "%zu activeBuffers, %zu unusedSlots)", allocatedSlots,
+                getMaxBufferCountLocked(), mFreeSlots.size(),
+                mFreeBuffers.size(), mActiveBuffers.size(),
+                mUnusedSlots.size());
+    }
 }
+#endif
 
 } // namespace android
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 87e5b4d..3e26e05 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -20,11 +20,18 @@
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 //#define LOG_NDEBUG 0
 
+#if DEBUG_ONLY_CODE
+#define VALIDATE_CONSISTENCY() do { mCore->validateConsistencyLocked(); } while (0)
+#else
+#define VALIDATE_CONSISTENCY()
+#endif
+
 #define EGL_EGLEXT_PROTOTYPES
 
 #include <gui/BufferItem.h>
 #include <gui/BufferQueueCore.h>
 #include <gui/BufferQueueProducer.h>
+#include <gui/GLConsumer.h>
 #include <gui/IConsumerListener.h>
 #include <gui/IGraphicBufferAlloc.h>
 #include <gui/IProducerListener.h>
@@ -43,7 +50,8 @@
     mCallbackMutex(),
     mNextCallbackTicket(0),
     mCurrentCallbackTicket(0),
-    mCallbackCondition() {}
+    mCallbackCondition(),
+    mDequeueTimeout(-1) {}
 
 BufferQueueProducer::~BufferQueueProducer() {}
 
@@ -57,13 +65,18 @@
         return NO_INIT;
     }
 
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("requestBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
         BQ_LOGE("requestBuffer: slot index %d out of range [0, %d)",
                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
         return BAD_VALUE;
-    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
+    } else if (!mSlots[slot].mBufferState.isDequeued()) {
         BQ_LOGE("requestBuffer: slot %d is not owned by the producer "
-                "(state = %d)", slot, mSlots[slot].mBufferState);
+                "(state = %s)", slot, mSlots[slot].mBufferState.string());
         return BAD_VALUE;
     }
 
@@ -72,9 +85,11 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueProducer::setBufferCount(int bufferCount) {
+status_t BufferQueueProducer::setMaxDequeuedBufferCount(
+        int maxDequeuedBuffers) {
     ATRACE_CALL();
-    BQ_LOGV("setBufferCount: count = %d", bufferCount);
+    BQ_LOGV("setMaxDequeuedBufferCount: maxDequeuedBuffers = %d",
+            maxDequeuedBuffers);
 
     sp<IConsumerListener> listener;
     { // Autolock scope
@@ -82,45 +97,65 @@
         mCore->waitWhileAllocatingLocked();
 
         if (mCore->mIsAbandoned) {
-            BQ_LOGE("setBufferCount: BufferQueue has been abandoned");
+            BQ_LOGE("setMaxDequeuedBufferCount: BufferQueue has been "
+                    "abandoned");
             return NO_INIT;
         }
 
-        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
-            BQ_LOGE("setBufferCount: bufferCount %d too large (max %d)",
-                    bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
-            return BAD_VALUE;
-        }
-
-        // There must be no dequeued buffers when changing the buffer count.
-        for (int s = 0; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-            if (mSlots[s].mBufferState == BufferSlot::DEQUEUED) {
-                BQ_LOGE("setBufferCount: buffer owned by producer");
-                return BAD_VALUE;
-            }
-        }
-
-        if (bufferCount == 0) {
-            mCore->mOverrideMaxBufferCount = 0;
-            mCore->mDequeueCondition.broadcast();
+        if (maxDequeuedBuffers == mCore->mMaxDequeuedBufferCount) {
             return NO_ERROR;
         }
 
-        const int minBufferSlots = mCore->getMinMaxBufferCountLocked(false);
-        if (bufferCount < minBufferSlots) {
-            BQ_LOGE("setBufferCount: requested buffer count %d is less than "
-                    "minimum %d", bufferCount, minBufferSlots);
+        // The new maxDequeuedBuffer count should not be violated by the number
+        // of currently dequeued buffers
+        int dequeuedCount = 0;
+        for (int s : mCore->mActiveBuffers) {
+            if (mSlots[s].mBufferState.isDequeued()) {
+                dequeuedCount++;
+            }
+        }
+        if (dequeuedCount > maxDequeuedBuffers) {
+            BQ_LOGE("setMaxDequeuedBufferCount: the requested maxDequeuedBuffer"
+                    "count (%d) exceeds the current dequeued buffer count (%d)",
+                    maxDequeuedBuffers, dequeuedCount);
             return BAD_VALUE;
         }
 
-        // Here we are guaranteed that the producer doesn't have any dequeued
-        // buffers and will release all of its buffer references. We don't
-        // clear the queue, however, so that currently queued buffers still
-        // get displayed.
-        mCore->freeAllBuffersLocked();
-        mCore->mOverrideMaxBufferCount = bufferCount;
+        int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
+        bufferCount += maxDequeuedBuffers;
+
+        if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
+            BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
+                    "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
+            return BAD_VALUE;
+        }
+
+        const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
+        if (bufferCount < minBufferSlots) {
+            BQ_LOGE("setMaxDequeuedBufferCount: requested buffer count %d is "
+                    "less than minimum %d", bufferCount, minBufferSlots);
+            return BAD_VALUE;
+        }
+
+        if (bufferCount > mCore->mMaxBufferCount) {
+            BQ_LOGE("setMaxDequeuedBufferCount: %d dequeued buffers would "
+                    "exceed the maxBufferCount (%d) (maxAcquired %d async %d "
+                    "mDequeuedBufferCannotBlock %d)", maxDequeuedBuffers,
+                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
+                    mCore->mAsyncMode, mCore->mDequeueBufferCannotBlock);
+            return BAD_VALUE;
+        }
+
+        int delta = maxDequeuedBuffers - mCore->mMaxDequeuedBufferCount;
+        if (!mCore->adjustAvailableSlotsLocked(delta)) {
+            return BAD_VALUE;
+        }
+        mCore->mMaxDequeuedBufferCount = maxDequeuedBuffers;
+        VALIDATE_CONSISTENCY();
+        if (delta < 0) {
+            listener = mCore->mConsumerListener;
+        }
         mCore->mDequeueCondition.broadcast();
-        listener = mCore->mConsumerListener;
     } // Autolock scope
 
     // Call back without lock held
@@ -131,100 +166,145 @@
     return NO_ERROR;
 }
 
-status_t BufferQueueProducer::waitForFreeSlotThenRelock(const char* caller,
-        bool async, int* found, status_t* returnFlags) const {
-    bool tryAgain = true;
-    while (tryAgain) {
+status_t BufferQueueProducer::setAsyncMode(bool async) {
+    ATRACE_CALL();
+    BQ_LOGV("setAsyncMode: async = %d", async);
+
+    sp<IConsumerListener> listener;
+    { // Autolock scope
+        Mutex::Autolock lock(mCore->mMutex);
+        mCore->waitWhileAllocatingLocked();
+
         if (mCore->mIsAbandoned) {
-            BQ_LOGE("%s: BufferQueue has been abandoned", caller);
+            BQ_LOGE("setAsyncMode: BufferQueue has been abandoned");
             return NO_INIT;
         }
 
-        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
-        if (async && mCore->mOverrideMaxBufferCount) {
-            // FIXME: Some drivers are manually setting the buffer count
-            // (which they shouldn't), so we do this extra test here to
-            // handle that case. This is TEMPORARY until we get this fixed.
-            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
-                BQ_LOGE("%s: async mode is invalid with buffer count override",
-                        caller);
-                return BAD_VALUE;
-            }
+        if (async == mCore->mAsyncMode) {
+            return NO_ERROR;
         }
 
-        // Free up any buffers that are in slots beyond the max buffer count
-        for (int s = maxBufferCount; s < BufferQueueDefs::NUM_BUFFER_SLOTS; ++s) {
-            assert(mSlots[s].mBufferState == BufferSlot::FREE);
-            if (mSlots[s].mGraphicBuffer != NULL) {
-                mCore->freeBufferLocked(s);
-                *returnFlags |= RELEASE_ALL_BUFFERS;
-            }
+        if ((mCore->mMaxAcquiredBufferCount + mCore->mMaxDequeuedBufferCount +
+                (async || mCore->mDequeueBufferCannotBlock ? 1 : 0)) >
+                mCore->mMaxBufferCount) {
+            BQ_LOGE("setAsyncMode(%d): this call would cause the "
+                    "maxBufferCount (%d) to be exceeded (maxAcquired %d "
+                    "maxDequeued %d mDequeueBufferCannotBlock %d)", async,
+                    mCore->mMaxBufferCount, mCore->mMaxAcquiredBufferCount,
+                    mCore->mMaxDequeuedBufferCount,
+                    mCore->mDequeueBufferCannotBlock);
+            return BAD_VALUE;
+        }
+
+        int delta = mCore->getMaxBufferCountLocked(async,
+                mCore->mDequeueBufferCannotBlock, mCore->mMaxBufferCount)
+                - mCore->getMaxBufferCountLocked();
+
+        if (!mCore->adjustAvailableSlotsLocked(delta)) {
+            BQ_LOGE("setAsyncMode: BufferQueue failed to adjust the number of "
+                    "available slots. Delta = %d", delta);
+            return BAD_VALUE;
+        }
+        mCore->mAsyncMode = async;
+        VALIDATE_CONSISTENCY();
+        mCore->mDequeueCondition.broadcast();
+        if (delta < 0) {
+            listener = mCore->mConsumerListener;
+        }
+    } // Autolock scope
+
+    // Call back without lock held
+    if (listener != NULL) {
+        listener->onBuffersReleased();
+    }
+    return NO_ERROR;
+}
+
+int BufferQueueProducer::getFreeBufferLocked() const {
+    if (mCore->mFreeBuffers.empty()) {
+        return BufferQueueCore::INVALID_BUFFER_SLOT;
+    }
+    int slot = mCore->mFreeBuffers.front();
+    mCore->mFreeBuffers.pop_front();
+    return slot;
+}
+
+int BufferQueueProducer::getFreeSlotLocked() const {
+    if (mCore->mFreeSlots.empty()) {
+        return BufferQueueCore::INVALID_BUFFER_SLOT;
+    }
+    int slot = *(mCore->mFreeSlots.begin());
+    mCore->mFreeSlots.erase(slot);
+    return slot;
+}
+
+status_t BufferQueueProducer::waitForFreeSlotThenRelock(FreeSlotCaller caller,
+        int* found) const {
+    auto callerString = (caller == FreeSlotCaller::Dequeue) ?
+            "dequeueBuffer" : "attachBuffer";
+    bool tryAgain = true;
+    while (tryAgain) {
+        if (mCore->mIsAbandoned) {
+            BQ_LOGE("%s: BufferQueue has been abandoned", callerString);
+            return NO_INIT;
         }
 
         int dequeuedCount = 0;
         int acquiredCount = 0;
-        for (int s = 0; s < maxBufferCount; ++s) {
-            switch (mSlots[s].mBufferState) {
-                case BufferSlot::DEQUEUED:
-                    ++dequeuedCount;
-                    break;
-                case BufferSlot::ACQUIRED:
-                    ++acquiredCount;
-                    break;
-                default:
-                    break;
+        for (int s : mCore->mActiveBuffers) {
+            if (mSlots[s].mBufferState.isDequeued()) {
+                ++dequeuedCount;
+            }
+            if (mSlots[s].mBufferState.isAcquired()) {
+                ++acquiredCount;
             }
         }
 
-        // Producers are not allowed to dequeue more than one buffer if they
-        // did not set a buffer count
-        if (!mCore->mOverrideMaxBufferCount && dequeuedCount) {
-            BQ_LOGE("%s: can't dequeue multiple buffers without setting the "
-                    "buffer count", caller);
+        // Producers are not allowed to dequeue more than
+        // mMaxDequeuedBufferCount buffers.
+        // This check is only done if a buffer has already been queued
+        if (mCore->mBufferHasBeenQueued &&
+                dequeuedCount >= mCore->mMaxDequeuedBufferCount) {
+            BQ_LOGE("%s: attempting to exceed the max dequeued buffer count "
+                    "(%d)", callerString, mCore->mMaxDequeuedBufferCount);
             return INVALID_OPERATION;
         }
 
-        // See whether a buffer has been queued since the last
-        // setBufferCount so we know whether to perform the min undequeued
-        // buffers check below
-        if (mCore->mBufferHasBeenQueued) {
-            // Make sure the producer is not trying to dequeue more buffers
-            // than allowed
-            const int newUndequeuedCount =
-                maxBufferCount - (dequeuedCount + 1);
-            const int minUndequeuedCount =
-                mCore->getMinUndequeuedBufferCountLocked(async);
-            if (newUndequeuedCount < minUndequeuedCount) {
-                BQ_LOGE("%s: min undequeued buffer count (%d) exceeded "
-                        "(dequeued=%d undequeued=%d)",
-                        caller, minUndequeuedCount,
-                        dequeuedCount, newUndequeuedCount);
-                return INVALID_OPERATION;
-            }
-        }
-
         *found = BufferQueueCore::INVALID_BUFFER_SLOT;
 
         // If we disconnect and reconnect quickly, we can be in a state where
         // our slots are empty but we have many buffers in the queue. This can
         // cause us to run out of memory if we outrun the consumer. Wait here if
         // it looks like we have too many buffers queued up.
+        const int maxBufferCount = mCore->getMaxBufferCountLocked();
         bool tooManyBuffers = mCore->mQueue.size()
                             > static_cast<size_t>(maxBufferCount);
         if (tooManyBuffers) {
-            BQ_LOGV("%s: queue size is %zu, waiting", caller,
+            BQ_LOGV("%s: queue size is %zu, waiting", callerString,
                     mCore->mQueue.size());
         } else {
-            if (!mCore->mFreeBuffers.empty()) {
-                auto slot = mCore->mFreeBuffers.begin();
-                *found = *slot;
-                mCore->mFreeBuffers.erase(slot);
-            } else if (mCore->mAllowAllocation && !mCore->mFreeSlots.empty()) {
-                auto slot = mCore->mFreeSlots.begin();
-                // Only return free slots up to the max buffer count
-                if (*slot < maxBufferCount) {
-                    *found = *slot;
-                    mCore->mFreeSlots.erase(slot);
+            // If in shared buffer mode and a shared buffer exists, always
+            // return it.
+            if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot !=
+                    BufferQueueCore::INVALID_BUFFER_SLOT) {
+                *found = mCore->mSharedBufferSlot;
+            } else {
+                if (caller == FreeSlotCaller::Dequeue) {
+                    // If we're calling this from dequeue, prefer free buffers
+                    int slot = getFreeBufferLocked();
+                    if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
+                        *found = slot;
+                    } else if (mCore->mAllowAllocation) {
+                        *found = getFreeSlotLocked();
+                    }
+                } else {
+                    // If we're calling this from attach, prefer free slots
+                    int slot = getFreeSlotLocked();
+                    if (slot != BufferQueueCore::INVALID_BUFFER_SLOT) {
+                        *found = slot;
+                    } else {
+                        *found = getFreeBufferLocked();
+                    }
                 }
             }
         }
@@ -241,11 +321,19 @@
             // buffer (which could cause us to have to wait here), which is
             // okay, since it is only used to implement an atomic acquire +
             // release (e.g., in GLConsumer::updateTexImage())
-            if (mCore->mDequeueBufferCannotBlock &&
+            if ((mCore->mDequeueBufferCannotBlock || mCore->mAsyncMode) &&
                     (acquiredCount <= mCore->mMaxAcquiredBufferCount)) {
                 return WOULD_BLOCK;
             }
-            mCore->mDequeueCondition.wait(mCore->mMutex);
+            if (mDequeueTimeout >= 0) {
+                status_t result = mCore->mDequeueCondition.waitRelative(
+                        mCore->mMutex, mDequeueTimeout);
+                if (result == TIMED_OUT) {
+                    return result;
+                }
+            } else {
+                mCore->mDequeueCondition.wait(mCore->mMutex);
+            }
         }
     } // while (tryAgain)
 
@@ -253,16 +341,26 @@
 }
 
 status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
-        sp<android::Fence> *outFence, bool async,
-        uint32_t width, uint32_t height, PixelFormat format, uint32_t usage) {
+        sp<android::Fence> *outFence, uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage) {
     ATRACE_CALL();
     { // Autolock scope
         Mutex::Autolock lock(mCore->mMutex);
         mConsumerName = mCore->mConsumerName;
+
+        if (mCore->mIsAbandoned) {
+            BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
+            return NO_INIT;
+        }
+
+        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+            BQ_LOGE("dequeueBuffer: BufferQueue has no connected producer");
+            return NO_INIT;
+        }
     } // Autolock scope
 
-    BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
-            async ? "true" : "false", width, height, format, usage);
+    BQ_LOGV("dequeueBuffer: w=%u h=%u format=%#x, usage=%#x", width, height,
+            format, usage);
 
     if ((width && !height) || (!width && height)) {
         BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
@@ -293,8 +391,8 @@
 
         int found = BufferItem::INVALID_BUFFER_SLOT;
         while (found == BufferItem::INVALID_BUFFER_SLOT) {
-            status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
-                    &found, &returnFlags);
+            status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Dequeue,
+                    &found);
             if (status != NO_ERROR) {
                 return status;
             }
@@ -313,21 +411,47 @@
             // requested attributes, we free it and attempt to get another one.
             if (!mCore->mAllowAllocation) {
                 if (buffer->needsReallocation(width, height, format, usage)) {
-                    mCore->freeBufferLocked(found);
+                    if (mCore->mSharedBufferSlot == found) {
+                        BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
+                                "buffer");
+                        return BAD_VALUE;
+                    }
+                    mCore->mFreeSlots.insert(found);
+                    mCore->clearBufferSlotLocked(found);
                     found = BufferItem::INVALID_BUFFER_SLOT;
                     continue;
                 }
             }
         }
 
+        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
+        if (mCore->mSharedBufferSlot == found &&
+                buffer->needsReallocation(width,  height, format, usage)) {
+            BQ_LOGE("dequeueBuffer: cannot re-allocate a shared"
+                    "buffer");
+
+            return BAD_VALUE;
+        }
+
+        if (mCore->mSharedBufferSlot != found) {
+            mCore->mActiveBuffers.insert(found);
+        }
         *outSlot = found;
         ATRACE_BUFFER_INDEX(found);
 
-        attachedByConsumer = mSlots[found].mAttachedByConsumer;
+        attachedByConsumer = mSlots[found].mNeedsReallocation;
+        mSlots[found].mNeedsReallocation = false;
 
-        mSlots[found].mBufferState = BufferSlot::DEQUEUED;
+        mSlots[found].mBufferState.dequeue();
 
-        const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
+        // If shared buffer mode has just been enabled, cache the slot of the
+        // first buffer that is dequeued and mark it as the shared buffer.
+        if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
+                BufferQueueCore::INVALID_BUFFER_SLOT) {
+            mCore->mSharedBufferSlot = found;
+            mSlots[found].mBufferState.mShared = true;
+        }
+
         if ((buffer == NULL) ||
                 buffer->needsReallocation(width, height, format, usage))
         {
@@ -338,6 +462,7 @@
             mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
             mSlots[found].mFence = Fence::NO_FENCE;
             mCore->mBufferAge = 0;
+            mCore->mIsAllocating = true;
 
             returnFlags |= BUFFER_NEEDS_REALLOCATION;
         } else {
@@ -361,8 +486,6 @@
         *outFence = mSlots[found].mFence;
         mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
         mSlots[found].mFence = Fence::NO_FENCE;
-
-        mCore->validateConsistencyLocked();
     } // Autolock scope
 
     if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
@@ -370,21 +493,28 @@
         BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
         sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                 width, height, format, usage, &error));
-        if (graphicBuffer == NULL) {
-            BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
-            return error;
-        }
-
         { // Autolock scope
             Mutex::Autolock lock(mCore->mMutex);
 
+            if (graphicBuffer != NULL && !mCore->mIsAbandoned) {
+                graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
+                mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
+            }
+
+            mCore->mIsAllocating = false;
+            mCore->mIsAllocatingCondition.broadcast();
+
+            if (graphicBuffer == NULL) {
+                BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
+                return error;
+            }
+
             if (mCore->mIsAbandoned) {
                 BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                 return NO_INIT;
             }
 
-            graphicBuffer->setGenerationNumber(mCore->mGenerationNumber);
-            mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
+            VALIDATE_CONSISTENCY();
         } // Autolock scope
     }
 
@@ -418,31 +548,44 @@
 status_t BufferQueueProducer::detachBuffer(int slot) {
     ATRACE_CALL();
     ATRACE_BUFFER_INDEX(slot);
-    BQ_LOGV("detachBuffer(P): slot %d", slot);
+    BQ_LOGV("detachBuffer: slot %d", slot);
     Mutex::Autolock lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
-        BQ_LOGE("detachBuffer(P): BufferQueue has been abandoned");
+        BQ_LOGE("detachBuffer: BufferQueue has been abandoned");
         return NO_INIT;
     }
 
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("detachBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    if (mCore->mSharedBufferMode || mCore->mSharedBufferSlot == slot) {
+        BQ_LOGE("detachBuffer: cannot detach a buffer in shared buffer mode");
+        return BAD_VALUE;
+    }
+
     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
-        BQ_LOGE("detachBuffer(P): slot index %d out of range [0, %d)",
+        BQ_LOGE("detachBuffer: slot index %d out of range [0, %d)",
                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
         return BAD_VALUE;
-    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
-        BQ_LOGE("detachBuffer(P): slot %d is not owned by the producer "
-                "(state = %d)", slot, mSlots[slot].mBufferState);
+    } else if (!mSlots[slot].mBufferState.isDequeued()) {
+        BQ_LOGE("detachBuffer: slot %d is not owned by the producer "
+                "(state = %s)", slot, mSlots[slot].mBufferState.string());
         return BAD_VALUE;
     } else if (!mSlots[slot].mRequestBufferCalled) {
-        BQ_LOGE("detachBuffer(P): buffer in slot %d has not been requested",
+        BQ_LOGE("detachBuffer: buffer in slot %d has not been requested",
                 slot);
         return BAD_VALUE;
     }
 
-    mCore->freeBufferLocked(slot);
+    mSlots[slot].mBufferState.detachProducer();
+    mCore->mActiveBuffers.erase(slot);
+    mCore->mFreeSlots.insert(slot);
+    mCore->clearBufferSlotLocked(slot);
     mCore->mDequeueCondition.broadcast();
-    mCore->validateConsistencyLocked();
+    VALIDATE_CONSISTENCY();
 
     return NO_ERROR;
 }
@@ -460,26 +603,39 @@
     }
 
     Mutex::Autolock lock(mCore->mMutex);
-    mCore->waitWhileAllocatingLocked();
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("detachNextBuffer: BufferQueue has been abandoned");
         return NO_INIT;
     }
 
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("detachNextBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    if (mCore->mSharedBufferMode) {
+        BQ_LOGE("detachNextBuffer: cannot detach a buffer in shared buffer "
+            "mode");
+        return BAD_VALUE;
+    }
+
+    mCore->waitWhileAllocatingLocked();
+
     if (mCore->mFreeBuffers.empty()) {
         return NO_MEMORY;
     }
 
     int found = mCore->mFreeBuffers.front();
     mCore->mFreeBuffers.remove(found);
+    mCore->mFreeSlots.insert(found);
 
     BQ_LOGV("detachNextBuffer detached slot %d", found);
 
     *outBuffer = mSlots[found].mGraphicBuffer;
     *outFence = mSlots[found].mFence;
-    mCore->freeBufferLocked(found);
-    mCore->validateConsistencyLocked();
+    mCore->clearBufferSlotLocked(found);
+    VALIDATE_CONSISTENCY();
 
     return NO_ERROR;
 }
@@ -489,15 +645,29 @@
     ATRACE_CALL();
 
     if (outSlot == NULL) {
-        BQ_LOGE("attachBuffer(P): outSlot must not be NULL");
+        BQ_LOGE("attachBuffer: outSlot must not be NULL");
         return BAD_VALUE;
     } else if (buffer == NULL) {
-        BQ_LOGE("attachBuffer(P): cannot attach NULL buffer");
+        BQ_LOGE("attachBuffer: cannot attach NULL buffer");
         return BAD_VALUE;
     }
 
     Mutex::Autolock lock(mCore->mMutex);
-    mCore->waitWhileAllocatingLocked();
+
+    if (mCore->mIsAbandoned) {
+        BQ_LOGE("attachBuffer: BufferQueue has been abandoned");
+        return NO_INIT;
+    }
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("attachBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    if (mCore->mSharedBufferMode) {
+        BQ_LOGE("attachBuffer: cannot attach a buffer in shared buffer mode");
+        return BAD_VALUE;
+    }
 
     if (buffer->getGenerationNumber() != mCore->mGenerationNumber) {
         BQ_LOGE("attachBuffer: generation number mismatch [buffer %u] "
@@ -506,35 +676,34 @@
         return BAD_VALUE;
     }
 
+    mCore->waitWhileAllocatingLocked();
+
     status_t returnFlags = NO_ERROR;
     int found;
-    // TODO: Should we provide an async flag to attachBuffer? It seems
-    // unlikely that buffers which we are attaching to a BufferQueue will
-    // be asynchronous (droppable), but it may not be impossible.
-    status_t status = waitForFreeSlotThenRelock("attachBuffer(P)", false,
-            &found, &returnFlags);
+    status_t status = waitForFreeSlotThenRelock(FreeSlotCaller::Attach, &found);
     if (status != NO_ERROR) {
         return status;
     }
 
     // This should not happen
     if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
-        BQ_LOGE("attachBuffer(P): no available buffer slots");
+        BQ_LOGE("attachBuffer: no available buffer slots");
         return -EBUSY;
     }
 
     *outSlot = found;
     ATRACE_BUFFER_INDEX(*outSlot);
-    BQ_LOGV("attachBuffer(P): returning slot %d flags=%#x",
+    BQ_LOGV("attachBuffer: returning slot %d flags=%#x",
             *outSlot, returnFlags);
 
     mSlots[*outSlot].mGraphicBuffer = buffer;
-    mSlots[*outSlot].mBufferState = BufferSlot::DEQUEUED;
+    mSlots[*outSlot].mBufferState.attachProducer();
     mSlots[*outSlot].mEglFence = EGL_NO_SYNC_KHR;
     mSlots[*outSlot].mFence = Fence::NO_FENCE;
     mSlots[*outSlot].mRequestBufferCalled = true;
-
-    mCore->validateConsistencyLocked();
+    mSlots[*outSlot].mAcquireCalled = false;
+    mCore->mActiveBuffers.insert(found);
+    VALIDATE_CONSISTENCY();
 
     return returnFlags;
 }
@@ -547,14 +716,13 @@
     int64_t timestamp;
     bool isAutoTimestamp;
     android_dataspace dataSpace;
-    Rect crop;
+    Rect crop(Rect::EMPTY_RECT);
     int scalingMode;
     uint32_t transform;
     uint32_t stickyTransform;
-    bool async;
     sp<Fence> fence;
     input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop, &scalingMode,
-            &transform, &async, &fence, &stickyTransform);
+            &transform, &fence, &stickyTransform);
     Region surfaceDamage = input.getSurfaceDamage();
 
     if (fence == NULL) {
@@ -585,25 +753,18 @@
             return NO_INIT;
         }
 
-        const int maxBufferCount = mCore->getMaxBufferCountLocked(async);
-        if (async && mCore->mOverrideMaxBufferCount) {
-            // FIXME: Some drivers are manually setting the buffer count
-            // (which they shouldn't), so we do this extra test here to
-            // handle that case. This is TEMPORARY until we get this fixed.
-            if (mCore->mOverrideMaxBufferCount < maxBufferCount) {
-                BQ_LOGE("queueBuffer: async mode is invalid with "
-                        "buffer count override");
-                return BAD_VALUE;
-            }
+        if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+            BQ_LOGE("queueBuffer: BufferQueue has no connected producer");
+            return NO_INIT;
         }
 
-        if (slot < 0 || slot >= maxBufferCount) {
+        if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
             BQ_LOGE("queueBuffer: slot index %d out of range [0, %d)",
-                    slot, maxBufferCount);
+                    slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
             return BAD_VALUE;
-        } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
+        } else if (!mSlots[slot].mBufferState.isDequeued()) {
             BQ_LOGE("queueBuffer: slot %d is not owned by the producer "
-                    "(state = %d)", slot, mSlots[slot].mBufferState);
+                    "(state = %s)", slot, mSlots[slot].mBufferState.string());
             return BAD_VALUE;
         } else if (!mSlots[slot].mRequestBufferCalled) {
             BQ_LOGE("queueBuffer: slot %d was queued without requesting "
@@ -611,6 +772,14 @@
             return BAD_VALUE;
         }
 
+        // If shared buffer mode has just been enabled, cache the slot of the
+        // first buffer that is queued and mark it as the shared buffer.
+        if (mCore->mSharedBufferMode && mCore->mSharedBufferSlot ==
+                BufferQueueCore::INVALID_BUFFER_SLOT) {
+            mCore->mSharedBufferSlot = slot;
+            mSlots[slot].mBufferState.mShared = true;
+        }
+
         BQ_LOGV("queueBuffer: slot=%d/%" PRIu64 " time=%" PRIu64 " dataSpace=%d"
                 " crop=[%d,%d,%d,%d] transform=%#x scale=%s",
                 slot, mCore->mFrameCounter + 1, timestamp, dataSpace,
@@ -619,7 +788,7 @@
 
         const sp<GraphicBuffer>& graphicBuffer(mSlots[slot].mGraphicBuffer);
         Rect bufferRect(graphicBuffer->getWidth(), graphicBuffer->getHeight());
-        Rect croppedRect;
+        Rect croppedRect(Rect::EMPTY_RECT);
         crop.intersect(bufferRect, &croppedRect);
         if (croppedRect != crop) {
             BQ_LOGE("queueBuffer: crop rect is not contained within the "
@@ -633,7 +802,8 @@
         }
 
         mSlots[slot].mFence = fence;
-        mSlots[slot].mBufferState = BufferSlot::QUEUED;
+        mSlots[slot].mBufferState.queue();
+
         ++mCore->mFrameCounter;
         mSlots[slot].mFrameNumber = mCore->mFrameCounter;
 
@@ -651,29 +821,55 @@
         item.mFrameNumber = mCore->mFrameCounter;
         item.mSlot = slot;
         item.mFence = fence;
-        item.mIsDroppable = mCore->mDequeueBufferCannotBlock || async;
+        item.mIsDroppable = mCore->mAsyncMode ||
+                mCore->mDequeueBufferCannotBlock ||
+                (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
         item.mSurfaceDamage = surfaceDamage;
+        item.mQueuedBuffer = true;
+        item.mAutoRefresh = mCore->mSharedBufferMode && mCore->mAutoRefresh;
 
         mStickyTransform = stickyTransform;
 
+        // Cache the shared buffer data so that the BufferItem can be recreated.
+        if (mCore->mSharedBufferMode) {
+            mCore->mSharedBufferCache.crop = crop;
+            mCore->mSharedBufferCache.transform = transform;
+            mCore->mSharedBufferCache.scalingMode = static_cast<uint32_t>(
+                    scalingMode);
+            mCore->mSharedBufferCache.dataspace = dataSpace;
+        }
+
         if (mCore->mQueue.empty()) {
             // When the queue is empty, we can ignore mDequeueBufferCannotBlock
             // and simply queue this buffer
             mCore->mQueue.push_back(item);
             frameAvailableListener = mCore->mConsumerListener;
         } else {
-            // When the queue is not empty, we need to look at the front buffer
-            // state to see if we need to replace it
-            BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
-            if (front->mIsDroppable) {
-                // If the front queued buffer is still being tracked, we first
-                // mark it as freed
-                if (mCore->stillTracking(front)) {
-                    mSlots[front->mSlot].mBufferState = BufferSlot::FREE;
-                    mCore->mFreeBuffers.push_front(front->mSlot);
+            // When the queue is not empty, we need to look at the last buffer
+            // in the queue to see if we need to replace it
+            const BufferItem& last = mCore->mQueue.itemAt(
+                    mCore->mQueue.size() - 1);
+            if (last.mIsDroppable) {
+
+                if (!last.mIsStale) {
+                    mSlots[last.mSlot].mBufferState.freeQueued();
+
+                    // After leaving shared buffer mode, the shared buffer will
+                    // still be around. Mark it as no longer shared if this
+                    // operation causes it to be free.
+                    if (!mCore->mSharedBufferMode &&
+                            mSlots[last.mSlot].mBufferState.isFree()) {
+                        mSlots[last.mSlot].mBufferState.mShared = false;
+                    }
+                    // Don't put the shared buffer on the free list.
+                    if (!mSlots[last.mSlot].mBufferState.isShared()) {
+                        mCore->mActiveBuffers.erase(last.mSlot);
+                        mCore->mFreeBuffers.push_back(last.mSlot);
+                    }
                 }
+
                 // Overwrite the droppable buffer with the incoming one
-                *front = item;
+                mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
                 frameReplacedListener = mCore->mConsumerListener;
             } else {
                 mCore->mQueue.push_back(item);
@@ -683,6 +879,7 @@
 
         mCore->mBufferHasBeenQueued = true;
         mCore->mDequeueCondition.broadcast();
+        mCore->mLastQueuedSlot = slot;
 
         output->inflate(mCore->mDefaultWidth, mCore->mDefaultHeight,
                 mCore->mTransformHint,
@@ -693,18 +890,9 @@
         // Take a ticket for the callback functions
         callbackTicket = mNextCallbackTicket++;
 
-        mCore->validateConsistencyLocked();
+        VALIDATE_CONSISTENCY();
     } // Autolock scope
 
-    // Wait without lock held
-    if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
-        // Waiting here allows for two full buffers to be queued but not a
-        // third. In the event that frames take varying time, this makes a
-        // small trade-off in favor of latency rather than throughput.
-        mLastQueueBufferFence->waitForever("Throttling EGL Production");
-        mLastQueueBufferFence = fence;
-    }
-
     // Don't send the GraphicBuffer through the callback, and don't send
     // the slot number, since the consumer shouldn't need it
     item.mGraphicBuffer.clear();
@@ -728,37 +916,72 @@
         mCallbackCondition.broadcast();
     }
 
+    // Wait without lock held
+    if (mCore->mConnectedApi == NATIVE_WINDOW_API_EGL) {
+        // Waiting here allows for two full buffers to be queued but not a
+        // third. In the event that frames take varying time, this makes a
+        // small trade-off in favor of latency rather than throughput.
+        mLastQueueBufferFence->waitForever("Throttling EGL Production");
+    }
+    mLastQueueBufferFence = fence;
+    mLastQueuedCrop = item.mCrop;
+    mLastQueuedTransform = item.mTransform;
+
     return NO_ERROR;
 }
 
-void BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+status_t BufferQueueProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
     ATRACE_CALL();
     BQ_LOGV("cancelBuffer: slot %d", slot);
     Mutex::Autolock lock(mCore->mMutex);
 
     if (mCore->mIsAbandoned) {
         BQ_LOGE("cancelBuffer: BufferQueue has been abandoned");
-        return;
+        return NO_INIT;
+    }
+
+    if (mCore->mConnectedApi == BufferQueueCore::NO_CONNECTED_API) {
+        BQ_LOGE("cancelBuffer: BufferQueue has no connected producer");
+        return NO_INIT;
+    }
+
+    if (mCore->mSharedBufferMode) {
+        BQ_LOGE("cancelBuffer: cannot cancel a buffer in shared buffer mode");
+        return BAD_VALUE;
     }
 
     if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
         BQ_LOGE("cancelBuffer: slot index %d out of range [0, %d)",
                 slot, BufferQueueDefs::NUM_BUFFER_SLOTS);
-        return;
-    } else if (mSlots[slot].mBufferState != BufferSlot::DEQUEUED) {
+        return BAD_VALUE;
+    } else if (!mSlots[slot].mBufferState.isDequeued()) {
         BQ_LOGE("cancelBuffer: slot %d is not owned by the producer "
-                "(state = %d)", slot, mSlots[slot].mBufferState);
-        return;
+                "(state = %s)", slot, mSlots[slot].mBufferState.string());
+        return BAD_VALUE;
     } else if (fence == NULL) {
         BQ_LOGE("cancelBuffer: fence is NULL");
-        return;
+        return BAD_VALUE;
     }
 
-    mCore->mFreeBuffers.push_front(slot);
-    mSlots[slot].mBufferState = BufferSlot::FREE;
+    mSlots[slot].mBufferState.cancel();
+
+    // After leaving shared buffer mode, the shared buffer will still be around.
+    // Mark it as no longer shared if this operation causes it to be free.
+    if (!mCore->mSharedBufferMode && mSlots[slot].mBufferState.isFree()) {
+        mSlots[slot].mBufferState.mShared = false;
+    }
+
+    // Don't put the shared buffer on the free list.
+    if (!mSlots[slot].mBufferState.isShared()) {
+        mCore->mActiveBuffers.erase(slot);
+        mCore->mFreeBuffers.push_back(slot);
+    }
+
     mSlots[slot].mFence = fence;
     mCore->mDequeueCondition.broadcast();
-    mCore->validateConsistencyLocked();
+    VALIDATE_CONSISTENCY();
+
+    return NO_ERROR;
 }
 
 int BufferQueueProducer::query(int what, int *outValue) {
@@ -787,7 +1010,7 @@
             value = static_cast<int32_t>(mCore->mDefaultBufferFormat);
             break;
         case NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS:
-            value = mCore->getMinUndequeuedBufferCountLocked(false);
+            value = mCore->getMinUndequeuedBufferCountLocked();
             break;
         case NATIVE_WINDOW_STICKY_TRANSFORM:
             value = static_cast<int32_t>(mStickyTransform);
@@ -822,30 +1045,41 @@
     ATRACE_CALL();
     Mutex::Autolock lock(mCore->mMutex);
     mConsumerName = mCore->mConsumerName;
-    BQ_LOGV("connect(P): api=%d producerControlledByApp=%s", api,
+    BQ_LOGV("connect: api=%d producerControlledByApp=%s", api,
             producerControlledByApp ? "true" : "false");
 
     if (mCore->mIsAbandoned) {
-        BQ_LOGE("connect(P): BufferQueue has been abandoned");
+        BQ_LOGE("connect: BufferQueue has been abandoned");
         return NO_INIT;
     }
 
     if (mCore->mConsumerListener == NULL) {
-        BQ_LOGE("connect(P): BufferQueue has no consumer");
+        BQ_LOGE("connect: BufferQueue has no consumer");
         return NO_INIT;
     }
 
     if (output == NULL) {
-        BQ_LOGE("connect(P): output was NULL");
+        BQ_LOGE("connect: output was NULL");
         return BAD_VALUE;
     }
 
     if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
-        BQ_LOGE("connect(P): already connected (cur=%d req=%d)",
+        BQ_LOGE("connect: already connected (cur=%d req=%d)",
                 mCore->mConnectedApi, api);
         return BAD_VALUE;
     }
 
+    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode,
+            mDequeueTimeout < 0 ?
+            mCore->mConsumerControlledByApp && producerControlledByApp : false,
+            mCore->mMaxBufferCount) -
+            mCore->getMaxBufferCountLocked();
+    if (!mCore->adjustAvailableSlotsLocked(delta)) {
+        BQ_LOGE("connect: BufferQueue failed to adjust the number of available "
+                "slots. Delta = %d", delta);
+        return BAD_VALUE;
+    }
+
     int status = NO_ERROR;
     switch (api) {
         case NATIVE_WINDOW_API_EGL:
@@ -864,29 +1098,33 @@
                 status = IInterface::asBinder(listener)->linkToDeath(
                         static_cast<IBinder::DeathRecipient*>(this));
                 if (status != NO_ERROR) {
-                    BQ_LOGE("connect(P): linkToDeath failed: %s (%d)",
+                    BQ_LOGE("connect: linkToDeath failed: %s (%d)",
                             strerror(-status), status);
                 }
             }
             mCore->mConnectedProducerListener = listener;
             break;
         default:
-            BQ_LOGE("connect(P): unknown API %d", api);
+            BQ_LOGE("connect: unknown API %d", api);
             status = BAD_VALUE;
             break;
     }
 
     mCore->mBufferHasBeenQueued = false;
-    mCore->mDequeueBufferCannotBlock =
-            mCore->mConsumerControlledByApp && producerControlledByApp;
-    mCore->mAllowAllocation = true;
+    mCore->mDequeueBufferCannotBlock = false;
+    if (mDequeueTimeout < 0) {
+        mCore->mDequeueBufferCannotBlock =
+                mCore->mConsumerControlledByApp && producerControlledByApp;
+    }
 
+    mCore->mAllowAllocation = true;
+    VALIDATE_CONSISTENCY();
     return status;
 }
 
 status_t BufferQueueProducer::disconnect(int api) {
     ATRACE_CALL();
-    BQ_LOGV("disconnect(P): api %d", api);
+    BQ_LOGV("disconnect: api %d", api);
 
     int status = NO_ERROR;
     sp<IConsumerListener> listener;
@@ -900,6 +1138,15 @@
             return NO_ERROR;
         }
 
+        if (api == BufferQueueCore::CURRENTLY_CONNECTED_API) {
+            api = mCore->mConnectedApi;
+            // If we're asked to disconnect the currently connected api but
+            // nobody is connected, it's not really an error.
+            if (api == BufferQueueCore::NO_CONNECTED_API) {
+                return NO_ERROR;
+            }
+        }
+
         switch (api) {
             case NATIVE_WINDOW_API_EGL:
             case NATIVE_WINDOW_API_CPU:
@@ -917,19 +1164,21 @@
                         token->unlinkToDeath(
                                 static_cast<IBinder::DeathRecipient*>(this));
                     }
+                    mCore->mSharedBufferSlot =
+                            BufferQueueCore::INVALID_BUFFER_SLOT;
                     mCore->mConnectedProducerListener = NULL;
                     mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API;
                     mCore->mSidebandStream.clear();
                     mCore->mDequeueCondition.broadcast();
                     listener = mCore->mConsumerListener;
                 } else if (mCore->mConnectedApi != BufferQueueCore::NO_CONNECTED_API) {
-                    BQ_LOGE("disconnect(P): still connected to another API "
+                    BQ_LOGE("disconnect: still connected to another API "
                             "(cur=%d req=%d)", mCore->mConnectedApi, api);
                     status = BAD_VALUE;
                 }
                 break;
             default:
-                BQ_LOGE("disconnect(P): unknown API %d", api);
+                BQ_LOGE("disconnect: unknown API %d", api);
                 status = BAD_VALUE;
                 break;
         }
@@ -957,11 +1206,10 @@
     return NO_ERROR;
 }
 
-void BufferQueueProducer::allocateBuffers(bool async, uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t usage) {
+void BufferQueueProducer::allocateBuffers(uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage) {
     ATRACE_CALL();
     while (true) {
-        Vector<int> freeSlots;
         size_t newBufferCount = 0;
         uint32_t allocWidth = 0;
         uint32_t allocHeight = 0;
@@ -977,32 +1225,11 @@
                 return;
             }
 
-            int currentBufferCount = 0;
-            for (int slot = 0; slot < BufferQueueDefs::NUM_BUFFER_SLOTS; ++slot) {
-                if (mSlots[slot].mGraphicBuffer != NULL) {
-                    ++currentBufferCount;
-                } else {
-                    if (mSlots[slot].mBufferState != BufferSlot::FREE) {
-                        BQ_LOGE("allocateBuffers: slot %d without buffer is not FREE",
-                                slot);
-                        continue;
-                    }
-
-                    freeSlots.push_back(slot);
-                }
-            }
-
-            int maxBufferCount = mCore->getMaxBufferCountLocked(async);
-            BQ_LOGV("allocateBuffers: allocating from %d buffers up to %d buffers",
-                    currentBufferCount, maxBufferCount);
-            if (maxBufferCount <= currentBufferCount)
-                return;
-            newBufferCount =
-                    static_cast<size_t>(maxBufferCount - currentBufferCount);
-            if (freeSlots.size() < newBufferCount) {
-                BQ_LOGE("allocateBuffers: ran out of free slots");
+            newBufferCount = mCore->mFreeSlots.size();
+            if (newBufferCount == 0) {
                 return;
             }
+
             allocWidth = width > 0 ? width : mCore->mDefaultWidth;
             allocHeight = height > 0 ? height : mCore->mDefaultHeight;
             allocFormat = format != 0 ? format : mCore->mDefaultBufferFormat;
@@ -1044,29 +1271,31 @@
             }
 
             for (size_t i = 0; i < newBufferCount; ++i) {
-                int slot = freeSlots[i];
-                if (mSlots[slot].mBufferState != BufferSlot::FREE) {
-                    // A consumer allocated the FREE slot with attachBuffer. Discard the buffer we
-                    // allocated.
-                    BQ_LOGV("allocateBuffers: slot %d was acquired while allocating. "
-                            "Dropping allocated buffer.", slot);
+                if (mCore->mFreeSlots.empty()) {
+                    BQ_LOGV("allocateBuffers: a slot was occupied while "
+                            "allocating. Dropping allocated buffer.");
                     continue;
                 }
-                mCore->freeBufferLocked(slot); // Clean up the slot first
-                mSlots[slot].mGraphicBuffer = buffers[i];
-                mSlots[slot].mFence = Fence::NO_FENCE;
+                auto slot = mCore->mFreeSlots.begin();
+                mCore->clearBufferSlotLocked(*slot); // Clean up the slot first
+                mSlots[*slot].mGraphicBuffer = buffers[i];
+                mSlots[*slot].mFence = Fence::NO_FENCE;
 
                 // freeBufferLocked puts this slot on the free slots list. Since
                 // we then attached a buffer, move the slot to free buffer list.
-                mCore->mFreeSlots.erase(slot);
-                mCore->mFreeBuffers.push_front(slot);
+                mCore->mFreeBuffers.push_front(*slot);
 
-                BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d", slot);
+                BQ_LOGV("allocateBuffers: allocated a new buffer in slot %d",
+                        *slot);
+
+                // Make sure the erase is done after all uses of the slot
+                // iterator since it will be invalid after this point.
+                mCore->mFreeSlots.erase(slot);
             }
 
             mCore->mIsAllocating = false;
             mCore->mIsAllocatingCondition.broadcast();
-            mCore->validateConsistencyLocked();
+            VALIDATE_CONSISTENCY();
         } // Autolock scope
     }
 }
@@ -1095,6 +1324,82 @@
     return mConsumerName;
 }
 
+uint64_t BufferQueueProducer::getNextFrameNumber() const {
+    ATRACE_CALL();
+
+    Mutex::Autolock lock(mCore->mMutex);
+    uint64_t nextFrameNumber = mCore->mFrameCounter + 1;
+    return nextFrameNumber;
+}
+
+status_t BufferQueueProducer::setSharedBufferMode(bool sharedBufferMode) {
+    ATRACE_CALL();
+    BQ_LOGV("setSharedBufferMode: %d", sharedBufferMode);
+
+    Mutex::Autolock lock(mCore->mMutex);
+    if (!sharedBufferMode) {
+        mCore->mSharedBufferSlot = BufferQueueCore::INVALID_BUFFER_SLOT;
+    }
+    mCore->mSharedBufferMode = sharedBufferMode;
+    return NO_ERROR;
+}
+
+status_t BufferQueueProducer::setAutoRefresh(bool autoRefresh) {
+    ATRACE_CALL();
+    BQ_LOGV("setAutoRefresh: %d", autoRefresh);
+
+    Mutex::Autolock lock(mCore->mMutex);
+
+    mCore->mAutoRefresh = autoRefresh;
+    return NO_ERROR;
+}
+
+status_t BufferQueueProducer::setDequeueTimeout(nsecs_t timeout) {
+    ATRACE_CALL();
+    BQ_LOGV("setDequeueTimeout: %" PRId64, timeout);
+
+    Mutex::Autolock lock(mCore->mMutex);
+    int delta = mCore->getMaxBufferCountLocked(mCore->mAsyncMode, false,
+            mCore->mMaxBufferCount) - mCore->getMaxBufferCountLocked();
+    if (!mCore->adjustAvailableSlotsLocked(delta)) {
+        BQ_LOGE("setDequeueTimeout: BufferQueue failed to adjust the number of "
+                "available slots. Delta = %d", delta);
+        return BAD_VALUE;
+    }
+
+    mDequeueTimeout = timeout;
+    mCore->mDequeueBufferCannotBlock = false;
+
+    VALIDATE_CONSISTENCY();
+    return NO_ERROR;
+}
+
+status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    ATRACE_CALL();
+    BQ_LOGV("getLastQueuedBuffer");
+
+    Mutex::Autolock lock(mCore->mMutex);
+    if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) {
+        *outBuffer = nullptr;
+        *outFence = Fence::NO_FENCE;
+        return NO_ERROR;
+    }
+
+    *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer;
+    *outFence = mLastQueueBufferFence;
+
+    // Currently only SurfaceFlinger internally ever changes
+    // GLConsumer's filtering mode, so we just use 'true' here as
+    // this is slightly specialized for the current client of this API,
+    // which does want filtering.
+    GLConsumer::computeTransformMatrix(outTransformMatrix,
+            mSlots[mCore->mLastQueuedSlot].mGraphicBuffer, mLastQueuedCrop,
+            mLastQueuedTransform, true /* filter */);
+
+    return NO_ERROR;
+}
+
 void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) {
     // If we're here, it means that a producer we were connected to died.
     // We're guaranteed that we are still connected to it because we remove
diff --git a/libs/gui/BufferSlot.cpp b/libs/gui/BufferSlot.cpp
index 01595de..b1cdc5d 100644
--- a/libs/gui/BufferSlot.cpp
+++ b/libs/gui/BufferSlot.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,14 +18,29 @@
 
 namespace android {
 
-const char* BufferSlot::bufferStateName(BufferState state) {
-    switch (state) {
-        case BufferSlot::DEQUEUED: return "DEQUEUED";
-        case BufferSlot::QUEUED: return "QUEUED";
-        case BufferSlot::FREE: return "FREE";
-        case BufferSlot::ACQUIRED: return "ACQUIRED";
+
+const char* BufferState::string() const {
+
+    if (isShared()) {
+        return "SHARED";
     }
-    return "Unknown";
+
+    if (isFree()) {
+        return "FREE";
+    }
+
+    if (isAcquired()) {
+        return "ACQUIRED";
+    }
+
+    if (isDequeued()) {
+        return "DEQUEUED";
+    }
+
+    if (isQueued()) {
+        return "QUEUED";
+    }
+    return "UNKNOWN";
 }
 
 } // namespace android
diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp
index 04ab06b..a6a9712 100644
--- a/libs/gui/ConsumerBase.cpp
+++ b/libs/gui/ConsumerBase.cpp
@@ -162,7 +162,11 @@
 }
 
 void ConsumerBase::abandonLocked() {
-	CB_LOGV("abandonLocked");
+    CB_LOGV("abandonLocked");
+    if (mAbandoned) {
+        CB_LOGE("abandonLocked: ConsumerBase is abandoned!");
+        return;
+    }
     for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
         freeBufferLocked(i);
     }
@@ -187,6 +191,11 @@
     CB_LOGV("detachBuffer");
     Mutex::Autolock lock(mMutex);
 
+    if (mAbandoned) {
+        CB_LOGE("detachBuffer: ConsumerBase is abandoned!");
+        return NO_INIT;
+    }
+
     status_t result = mConsumer->detachBuffer(slot);
     if (result != NO_ERROR) {
         CB_LOGE("Failed to detach buffer: %d", result);
@@ -200,17 +209,29 @@
 
 status_t ConsumerBase::setDefaultBufferSize(uint32_t width, uint32_t height) {
     Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        CB_LOGE("setDefaultBufferSize: ConsumerBase is abandoned!");
+        return NO_INIT;
+    }
     return mConsumer->setDefaultBufferSize(width, height);
 }
 
 status_t ConsumerBase::setDefaultBufferFormat(PixelFormat defaultFormat) {
     Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        CB_LOGE("setDefaultBufferFormat: ConsumerBase is abandoned!");
+        return NO_INIT;
+    }
     return mConsumer->setDefaultBufferFormat(defaultFormat);
 }
 
 status_t ConsumerBase::setDefaultBufferDataSpace(
         android_dataspace defaultDataSpace) {
     Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        CB_LOGE("setDefaultBufferDataSpace: ConsumerBase is abandoned!");
+        return NO_INIT;
+    }
     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
 }
 
@@ -233,20 +254,25 @@
 
 status_t ConsumerBase::acquireBufferLocked(BufferItem *item,
         nsecs_t presentWhen, uint64_t maxFrameNumber) {
+    if (mAbandoned) {
+        CB_LOGE("acquireBufferLocked: ConsumerBase is abandoned!");
+        return NO_INIT;
+    }
+
     status_t err = mConsumer->acquireBuffer(item, presentWhen, maxFrameNumber);
     if (err != NO_ERROR) {
         return err;
     }
 
     if (item->mGraphicBuffer != NULL) {
-        mSlots[item->mBuf].mGraphicBuffer = item->mGraphicBuffer;
+        mSlots[item->mSlot].mGraphicBuffer = item->mGraphicBuffer;
     }
 
-    mSlots[item->mBuf].mFrameNumber = item->mFrameNumber;
-    mSlots[item->mBuf].mFence = item->mFence;
+    mSlots[item->mSlot].mFrameNumber = item->mFrameNumber;
+    mSlots[item->mSlot].mFence = item->mFence;
 
     CB_LOGV("acquireBufferLocked: -> slot=%d/%" PRIu64,
-            item->mBuf, item->mFrameNumber);
+            item->mSlot, item->mFrameNumber);
 
     return OK;
 }
@@ -289,6 +315,10 @@
 status_t ConsumerBase::releaseBufferLocked(
         int slot, const sp<GraphicBuffer> graphicBuffer,
         EGLDisplay display, EGLSyncKHR eglFence) {
+    if (mAbandoned) {
+        CB_LOGE("releaseBufferLocked: ConsumerBase is abandoned!");
+        return NO_INIT;
+    }
     // If consumer no longer tracks this graphicBuffer (we received a new
     // buffer on the same slot), the buffer producer is definitely no longer
     // tracking it.
diff --git a/libs/gui/CpuConsumer.cpp b/libs/gui/CpuConsumer.cpp
index e29b740..8393160 100644
--- a/libs/gui/CpuConsumer.cpp
+++ b/libs/gui/CpuConsumer.cpp
@@ -52,6 +52,10 @@
 
 void CpuConsumer::setName(const String8& name) {
     Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        CC_LOGE("setName: CpuConsumer is abandoned!");
+        return;
+    }
     mName = name;
     mConsumer->setConsumerName(name);
 }
@@ -106,22 +110,22 @@
         }
     }
 
-    int buf = b.mBuf;
+    int slot = b.mSlot;
 
     void *bufferPointer = NULL;
     android_ycbcr ycbcr = android_ycbcr();
 
-    PixelFormat format = mSlots[buf].mGraphicBuffer->getPixelFormat();
+    PixelFormat format = mSlots[slot].mGraphicBuffer->getPixelFormat();
     PixelFormat flexFormat = format;
     if (isPossiblyYUV(format)) {
         if (b.mFence.get()) {
-            err = mSlots[buf].mGraphicBuffer->lockAsyncYCbCr(
+            err = mSlots[slot].mGraphicBuffer->lockAsyncYCbCr(
                 GraphicBuffer::USAGE_SW_READ_OFTEN,
                 b.mCrop,
                 &ycbcr,
                 b.mFence->dup());
         } else {
-            err = mSlots[buf].mGraphicBuffer->lockYCbCr(
+            err = mSlots[slot].mGraphicBuffer->lockYCbCr(
                 GraphicBuffer::USAGE_SW_READ_OFTEN,
                 b.mCrop,
                 &ycbcr);
@@ -141,13 +145,13 @@
 
     if (bufferPointer == NULL) { // not flexible YUV
         if (b.mFence.get()) {
-            err = mSlots[buf].mGraphicBuffer->lockAsync(
+            err = mSlots[slot].mGraphicBuffer->lockAsync(
                 GraphicBuffer::USAGE_SW_READ_OFTEN,
                 b.mCrop,
                 &bufferPointer,
                 b.mFence->dup());
         } else {
-            err = mSlots[buf].mGraphicBuffer->lock(
+            err = mSlots[slot].mGraphicBuffer->lock(
                 GraphicBuffer::USAGE_SW_READ_OFTEN,
                 b.mCrop,
                 &bufferPointer);
@@ -169,19 +173,19 @@
     assert(lockedIdx < mMaxLockedBuffers);
 
     AcquiredBuffer &ab = mAcquiredBuffers.editItemAt(lockedIdx);
-    ab.mSlot = buf;
+    ab.mSlot = slot;
     ab.mBufferPointer = bufferPointer;
-    ab.mGraphicBuffer = mSlots[buf].mGraphicBuffer;
+    ab.mGraphicBuffer = mSlots[slot].mGraphicBuffer;
 
     nativeBuffer->data   =
             reinterpret_cast<uint8_t*>(bufferPointer);
-    nativeBuffer->width  = mSlots[buf].mGraphicBuffer->getWidth();
-    nativeBuffer->height = mSlots[buf].mGraphicBuffer->getHeight();
+    nativeBuffer->width  = mSlots[slot].mGraphicBuffer->getWidth();
+    nativeBuffer->height = mSlots[slot].mGraphicBuffer->getHeight();
     nativeBuffer->format = format;
     nativeBuffer->flexFormat = flexFormat;
     nativeBuffer->stride = (ycbcr.y != NULL) ?
             static_cast<uint32_t>(ycbcr.ystride) :
-            mSlots[buf].mGraphicBuffer->getStride();
+            mSlots[slot].mGraphicBuffer->getStride();
 
     nativeBuffer->crop        = b.mCrop;
     nativeBuffer->transform   = b.mTransform;
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 757e08a..a06c7b5 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -44,6 +44,8 @@
 
 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 #define CROP_EXT_STR "EGL_ANDROID_image_crop"
+#define PROT_CONTENT_EXT_STR "EGL_EXT_protected_content"
+#define EGL_PROTECTED_CONTENT_EXT 0x32C0
 
 namespace android {
 
@@ -123,6 +125,27 @@
     return hasIt;
 }
 
+static bool hasEglProtectedContentImpl() {
+    EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    const char* exts = eglQueryString(dpy, EGL_EXTENSIONS);
+    size_t cropExtLen = strlen(PROT_CONTENT_EXT_STR);
+    size_t extsLen = strlen(exts);
+    bool equal = !strcmp(PROT_CONTENT_EXT_STR, exts);
+    bool atStart = !strncmp(PROT_CONTENT_EXT_STR " ", exts, cropExtLen+1);
+    bool atEnd = (cropExtLen+1) < extsLen &&
+            !strcmp(" " PROT_CONTENT_EXT_STR, exts + extsLen - (cropExtLen+1));
+    bool inMiddle = strstr(exts, " " PROT_CONTENT_EXT_STR " ");
+    return ENABLE_GPU_PROTECTED_CONTENT &&
+            (equal || atStart || atEnd || inMiddle);
+}
+
+static bool hasEglProtectedContent() {
+    // Only compute whether the extension is present once the first time this
+    // function is called.
+    static bool hasIt = hasEglProtectedContentImpl();
+    return hasIt;
+}
+
 static bool isEglImageCroppable(const Rect& crop) {
     return hasEglAndroidImageCrop() && (crop.left == 0 && crop.top == 0);
 }
@@ -130,6 +153,7 @@
 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t tex,
         uint32_t texTarget, bool useFenceSync, bool isControlledByApp) :
     ConsumerBase(bq, isControlledByApp),
+    mCurrentCrop(Rect::EMPTY_RECT),
     mCurrentTransform(0),
     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mCurrentFence(Fence::NO_FENCE),
@@ -157,6 +181,7 @@
 GLConsumer::GLConsumer(const sp<IGraphicBufferConsumer>& bq, uint32_t texTarget,
         bool useFenceSync, bool isControlledByApp) :
     ConsumerBase(bq, isControlledByApp),
+    mCurrentCrop(Rect::EMPTY_RECT),
     mCurrentTransform(0),
     mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
     mCurrentFence(Fence::NO_FENCE),
@@ -181,15 +206,13 @@
     mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
 }
 
-status_t GLConsumer::setDefaultMaxBufferCount(int bufferCount) {
-    Mutex::Autolock lock(mMutex);
-    return mConsumer->setDefaultMaxBufferCount(bufferCount);
-}
-
-
 status_t GLConsumer::setDefaultBufferSize(uint32_t w, uint32_t h)
 {
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setDefaultBufferSize: GLConsumer is abandoned!");
+        return NO_INIT;
+    }
     mDefaultWidth = w;
     mDefaultHeight = h;
     return mConsumer->setDefaultBufferSize(w, h);
@@ -298,7 +321,6 @@
         mCurrentTextureImage = mReleasedTexImage;
         mCurrentCrop.makeInvalid();
         mCurrentTransform = 0;
-        mCurrentScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
         mCurrentTimestamp = 0;
         mCurrentFence = Fence::NO_FENCE;
 
@@ -355,7 +377,7 @@
     // before, so any prior EglImage created is using a stale buffer. This
     // replaces any old EglImage with a new one (using the new buffer).
     if (item->mGraphicBuffer != NULL) {
-        int slot = item->mBuf;
+        int slot = item->mSlot;
         mEglSlots[slot].mEglImage = new EglImage(item->mGraphicBuffer);
     }
 
@@ -375,16 +397,17 @@
     return err;
 }
 
-status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item)
+status_t GLConsumer::updateAndReleaseLocked(const BufferItem& item,
+        PendingRelease* pendingRelease)
 {
     status_t err = NO_ERROR;
 
-    int buf = item.mBuf;
+    int slot = item.mSlot;
 
     if (!mAttached) {
         GLC_LOGE("updateAndRelease: GLConsumer is not attached to an OpenGL "
                 "ES context");
-        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                 mEglDisplay, EGL_NO_SYNC_KHR);
         return INVALID_OPERATION;
     }
@@ -392,7 +415,7 @@
     // Confirm state.
     err = checkAndUpdateEglStateLocked();
     if (err != NO_ERROR) {
-        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                 mEglDisplay, EGL_NO_SYNC_KHR);
         return err;
     }
@@ -402,48 +425,64 @@
     // ConsumerBase.
     // We may have to do this even when item.mGraphicBuffer == NULL (which
     // means the buffer was previously acquired).
-    err = mEglSlots[buf].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
+    err = mEglSlots[slot].mEglImage->createIfNeeded(mEglDisplay, item.mCrop);
     if (err != NO_ERROR) {
         GLC_LOGW("updateAndRelease: unable to createImage on display=%p slot=%d",
-                mEglDisplay, buf);
-        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
+                mEglDisplay, slot);
+        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
                 mEglDisplay, EGL_NO_SYNC_KHR);
         return UNKNOWN_ERROR;
     }
 
     // Do whatever sync ops we need to do before releasing the old slot.
-    err = syncForReleaseLocked(mEglDisplay);
-    if (err != NO_ERROR) {
-        // Release the buffer we just acquired.  It's not safe to
-        // release the old buffer, so instead we just drop the new frame.
-        // As we are still under lock since acquireBuffer, it is safe to
-        // release by slot.
-        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer,
-                mEglDisplay, EGL_NO_SYNC_KHR);
-        return err;
+    if (slot != mCurrentTexture) {
+        err = syncForReleaseLocked(mEglDisplay);
+        if (err != NO_ERROR) {
+            // Release the buffer we just acquired.  It's not safe to
+            // release the old buffer, so instead we just drop the new frame.
+            // As we are still under lock since acquireBuffer, it is safe to
+            // release by slot.
+            releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer,
+                    mEglDisplay, EGL_NO_SYNC_KHR);
+            return err;
+        }
     }
 
     GLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)",
             mCurrentTexture, mCurrentTextureImage != NULL ?
                     mCurrentTextureImage->graphicBufferHandle() : 0,
-            buf, mSlots[buf].mGraphicBuffer->handle);
+            slot, mSlots[slot].mGraphicBuffer->handle);
+
+    // Hang onto the pointer so that it isn't freed in the call to
+    // releaseBufferLocked() if we're in shared buffer mode and both buffers are
+    // the same.
+    sp<EglImage> nextTextureImage = mEglSlots[slot].mEglImage;
 
     // release old buffer
     if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
-        status_t status = releaseBufferLocked(
-                mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
-                mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
-        if (status < NO_ERROR) {
-            GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
-                   strerror(-status), status);
-            err = status;
-            // keep going, with error raised [?]
+        if (pendingRelease == nullptr) {
+            status_t status = releaseBufferLocked(
+                    mCurrentTexture, mCurrentTextureImage->graphicBuffer(),
+                    mEglDisplay, mEglSlots[mCurrentTexture].mEglFence);
+            if (status < NO_ERROR) {
+                GLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)",
+                        strerror(-status), status);
+                err = status;
+                // keep going, with error raised [?]
+            }
+        } else {
+            pendingRelease->currentTexture = mCurrentTexture;
+            pendingRelease->graphicBuffer =
+                    mCurrentTextureImage->graphicBuffer();
+            pendingRelease->display = mEglDisplay;
+            pendingRelease->fence = mEglSlots[mCurrentTexture].mEglFence;
+            pendingRelease->isPending = true;
         }
     }
 
     // Update the GLConsumer state.
-    mCurrentTexture = buf;
-    mCurrentTextureImage = mEglSlots[buf].mEglImage;
+    mCurrentTexture = slot;
+    mCurrentTextureImage = nextTextureImage;
     mCurrentCrop = item.mCrop;
     mCurrentTransform = item.mTransform;
     mCurrentScalingMode = item.mScalingMode;
@@ -760,26 +799,40 @@
 
 void GLConsumer::computeCurrentTransformMatrixLocked() {
     GLC_LOGV("computeCurrentTransformMatrixLocked");
+    sp<GraphicBuffer> buf = (mCurrentTextureImage == nullptr) ?
+            nullptr : mCurrentTextureImage->graphicBuffer();
+    if (buf == nullptr) {
+        GLC_LOGD("computeCurrentTransformMatrixLocked: "
+                "mCurrentTextureImage is NULL");
+    }
+    computeTransformMatrix(mCurrentTransformMatrix, buf,
+        isEglImageCroppable(mCurrentCrop) ? Rect::EMPTY_RECT : mCurrentCrop,
+        mCurrentTransform, mFilteringEnabled);
+}
+
+void GLConsumer::computeTransformMatrix(float outTransform[16],
+        const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
+        bool filtering) {
 
     float xform[16];
     for (int i = 0; i < 16; i++) {
         xform[i] = mtxIdentity[i];
     }
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
         float result[16];
         mtxMul(result, xform, mtxFlipH);
         for (int i = 0; i < 16; i++) {
             xform[i] = result[i];
         }
     }
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+    if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
         float result[16];
         mtxMul(result, xform, mtxFlipV);
         for (int i = 0; i < 16; i++) {
             xform[i] = result[i];
         }
     }
-    if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+    if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
         float result[16];
         mtxMul(result, xform, mtxRot90);
         for (int i = 0; i < 16; i++) {
@@ -787,59 +840,49 @@
         }
     }
 
-    sp<GraphicBuffer> buf = (mCurrentTextureImage == NULL) ?
-            NULL : mCurrentTextureImage->graphicBuffer();
-
-    if (buf == NULL) {
-        GLC_LOGD("computeCurrentTransformMatrixLocked: mCurrentTextureImage is NULL");
-    }
-
     float mtxBeforeFlipV[16];
-    if (!isEglImageCroppable(mCurrentCrop)) {
-        Rect cropRect = mCurrentCrop;
+    if (!cropRect.isEmpty()) {
         float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
         float bufferWidth = buf->getWidth();
         float bufferHeight = buf->getHeight();
-        if (!cropRect.isEmpty()) {
-            float shrinkAmount = 0.0f;
-            if (mFilteringEnabled) {
-                // In order to prevent bilinear sampling beyond the edge of the
-                // crop rectangle we may need to shrink it by 2 texels in each
-                // dimension.  Normally this would just need to take 1/2 a texel
-                // off each end, but because the chroma channels of YUV420 images
-                // are subsampled we may need to shrink the crop region by a whole
-                // texel on each side.
-                switch (buf->getPixelFormat()) {
-                    case PIXEL_FORMAT_RGBA_8888:
-                    case PIXEL_FORMAT_RGBX_8888:
-                    case PIXEL_FORMAT_RGB_888:
-                    case PIXEL_FORMAT_RGB_565:
-                    case PIXEL_FORMAT_BGRA_8888:
-                        // We know there's no subsampling of any channels, so we
-                        // only need to shrink by a half a pixel.
-                        shrinkAmount = 0.5;
-                        break;
+        float shrinkAmount = 0.0f;
+        if (filtering) {
+            // In order to prevent bilinear sampling beyond the edge of the
+            // crop rectangle we may need to shrink it by 2 texels in each
+            // dimension.  Normally this would just need to take 1/2 a texel
+            // off each end, but because the chroma channels of YUV420 images
+            // are subsampled we may need to shrink the crop region by a whole
+            // texel on each side.
+            switch (buf->getPixelFormat()) {
+                case PIXEL_FORMAT_RGBA_8888:
+                case PIXEL_FORMAT_RGBX_8888:
+                case PIXEL_FORMAT_RGB_888:
+                case PIXEL_FORMAT_RGB_565:
+                case PIXEL_FORMAT_BGRA_8888:
+                    // We know there's no subsampling of any channels, so we
+                    // only need to shrink by a half a pixel.
+                    shrinkAmount = 0.5;
+                    break;
 
-                    default:
-                        // If we don't recognize the format, we must assume the
-                        // worst case (that we care about), which is YUV420.
-                        shrinkAmount = 1.0;
-                        break;
-                }
+                default:
+                    // If we don't recognize the format, we must assume the
+                    // worst case (that we care about), which is YUV420.
+                    shrinkAmount = 1.0;
+                    break;
             }
+        }
 
-            // Only shrink the dimensions that are not the size of the buffer.
-            if (cropRect.width() < bufferWidth) {
-                tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
-                sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
-                        bufferWidth;
-            }
-            if (cropRect.height() < bufferHeight) {
-                ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
-                        bufferHeight;
-                sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
-                        bufferHeight;
-            }
+        // Only shrink the dimensions that are not the size of the buffer.
+        if (cropRect.width() < bufferWidth) {
+            tx = (float(cropRect.left) + shrinkAmount) / bufferWidth;
+            sx = (float(cropRect.width()) - (2.0f * shrinkAmount)) /
+                    bufferWidth;
+        }
+        if (cropRect.height() < bufferHeight) {
+            ty = (float(bufferHeight - cropRect.bottom) + shrinkAmount) /
+                    bufferHeight;
+            sy = (float(cropRect.height()) - (2.0f * shrinkAmount)) /
+                    bufferHeight;
         }
         float crop[16] = {
             sx, 0, 0, 0,
@@ -859,7 +902,7 @@
     // coordinate of 0, so GLConsumer must behave the same way.  We don't
     // want to expose this to applications, however, so we must add an
     // additional vertical flip to the transform after all the other transforms.
-    mtxMul(mCurrentTransformMatrix, mtxFlipV, mtxBeforeFlipV);
+    mtxMul(outTransform, mtxFlipV, mtxBeforeFlipV);
 }
 
 nsecs_t GLConsumer::getTimestamp() {
@@ -1020,32 +1063,61 @@
 
 void GLConsumer::setName(const String8& name) {
     Mutex::Autolock _l(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setName: GLConsumer is abandoned!");
+        return;
+    }
     mName = name;
     mConsumer->setConsumerName(name);
 }
 
 status_t GLConsumer::setDefaultBufferFormat(PixelFormat defaultFormat) {
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setDefaultBufferFormat: GLConsumer is abandoned!");
+        return NO_INIT;
+    }
     return mConsumer->setDefaultBufferFormat(defaultFormat);
 }
 
 status_t GLConsumer::setDefaultBufferDataSpace(
         android_dataspace defaultDataSpace) {
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setDefaultBufferDataSpace: GLConsumer is abandoned!");
+        return NO_INIT;
+    }
     return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
 }
 
 status_t GLConsumer::setConsumerUsageBits(uint32_t usage) {
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setConsumerUsageBits: GLConsumer is abandoned!");
+        return NO_INIT;
+    }
     usage |= DEFAULT_USAGE_FLAGS;
     return mConsumer->setConsumerUsageBits(usage);
 }
 
 status_t GLConsumer::setTransformHint(uint32_t hint) {
     Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setTransformHint: GLConsumer is abandoned!");
+        return NO_INIT;
+    }
     return mConsumer->setTransformHint(hint);
 }
 
+status_t GLConsumer::setMaxAcquiredBufferCount(int maxAcquiredBuffers) {
+    Mutex::Autolock lock(mMutex);
+    if (mAbandoned) {
+        GLC_LOGE("setMaxAcquiredBufferCount: GLConsumer is abandoned!");
+        return NO_INIT;
+    }
+    return mConsumer->setMaxAcquiredBufferCount(maxAcquiredBuffers);
+}
+
 void GLConsumer::dumpLocked(String8& result, const char* prefix) const
 {
     result.appendFormat(
@@ -1083,7 +1155,8 @@
 GLConsumer::EglImage::EglImage(sp<GraphicBuffer> graphicBuffer) :
     mGraphicBuffer(graphicBuffer),
     mEglImage(EGL_NO_IMAGE_KHR),
-    mEglDisplay(EGL_NO_DISPLAY) {
+    mEglDisplay(EGL_NO_DISPLAY),
+    mCropRect(Rect::EMPTY_RECT) {
 }
 
 GLConsumer::EglImage::~EglImage() {
@@ -1141,12 +1214,17 @@
         const sp<GraphicBuffer>& graphicBuffer, const Rect& crop) {
     EGLClientBuffer cbuf =
             static_cast<EGLClientBuffer>(graphicBuffer->getNativeBuffer());
+    const bool createProtectedImage =
+            (graphicBuffer->getUsage() & GRALLOC_USAGE_PROTECTED) &&
+            hasEglProtectedContent();
     EGLint attrs[] = {
         EGL_IMAGE_PRESERVED_KHR,        EGL_TRUE,
         EGL_IMAGE_CROP_LEFT_ANDROID,    crop.left,
         EGL_IMAGE_CROP_TOP_ANDROID,     crop.top,
         EGL_IMAGE_CROP_RIGHT_ANDROID,   crop.right,
         EGL_IMAGE_CROP_BOTTOM_ANDROID,  crop.bottom,
+        createProtectedImage ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
+        createProtectedImage ? EGL_TRUE : EGL_NONE,
         EGL_NONE,
     };
     if (!crop.isValid()) {
diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp
index 7ae82e0..cb1ad35 100644
--- a/libs/gui/IGraphicBufferConsumer.cpp
+++ b/libs/gui/IGraphicBufferConsumer.cpp
@@ -43,8 +43,7 @@
     CONSUMER_DISCONNECT,
     GET_RELEASED_BUFFERS,
     SET_DEFAULT_BUFFER_SIZE,
-    SET_DEFAULT_MAX_BUFFER_COUNT,
-    DISABLE_ASYNC_BUFFER,
+    SET_MAX_BUFFER_COUNT,
     SET_MAX_ACQUIRED_BUFFER_COUNT,
     SET_CONSUMER_NAME,
     SET_DEFAULT_BUFFER_FORMAT,
@@ -172,21 +171,11 @@
         return reply.readInt32();
     }
 
-    virtual status_t setDefaultMaxBufferCount(int bufferCount) {
+    virtual status_t setMaxBufferCount(int bufferCount) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
         data.writeInt32(bufferCount);
-        status_t result = remote()->transact(SET_DEFAULT_MAX_BUFFER_COUNT, data, &reply);
-        if (result != NO_ERROR) {
-            return result;
-        }
-        return reply.readInt32();
-    }
-
-    virtual status_t disableAsyncBuffer() {
-        Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor());
-        status_t result = remote()->transact(DISABLE_ASYNC_BUFFER, data, &reply);
+        status_t result = remote()->transact(SET_MAX_BUFFER_COUNT, data, &reply);
         if (result != NO_ERROR) {
             return result;
         }
@@ -363,16 +352,10 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
-        case SET_DEFAULT_MAX_BUFFER_COUNT: {
+        case SET_MAX_BUFFER_COUNT: {
             CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
             int bufferCount = data.readInt32();
-            status_t result = setDefaultMaxBufferCount(bufferCount);
-            reply->writeInt32(result);
-            return NO_ERROR;
-        }
-        case DISABLE_ASYNC_BUFFER: {
-            CHECK_INTERFACE(IGraphicBufferConsumer, data, reply);
-            status_t result = disableAsyncBuffer();
+            status_t result = setMaxBufferCount(bufferCount);
             reply->writeInt32(result);
             return NO_ERROR;
         }
diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp
index c3c6235..2c48d83 100644
--- a/libs/gui/IGraphicBufferProducer.cpp
+++ b/libs/gui/IGraphicBufferProducer.cpp
@@ -34,7 +34,6 @@
 
 enum {
     REQUEST_BUFFER = IBinder::FIRST_CALL_TRANSACTION,
-    SET_BUFFER_COUNT,
     DEQUEUE_BUFFER,
     DETACH_BUFFER,
     DETACH_NEXT_BUFFER,
@@ -49,6 +48,13 @@
     ALLOW_ALLOCATION,
     SET_GENERATION_NUMBER,
     GET_CONSUMER_NAME,
+    SET_MAX_DEQUEUED_BUFFER_COUNT,
+    SET_ASYNC_MODE,
+    GET_NEXT_FRAME_NUMBER,
+    SET_SHARED_BUFFER_MODE,
+    SET_AUTO_REFRESH,
+    SET_DEQUEUE_TIMEOUT,
+    GET_LAST_QUEUED_BUFFER,
 };
 
 class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer>
@@ -82,12 +88,13 @@
         return result;
     }
 
-    virtual status_t setBufferCount(int bufferCount)
-    {
+    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
         Parcel data, reply;
-        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(bufferCount);
-        status_t result =remote()->transact(SET_BUFFER_COUNT, data, &reply);
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(maxDequeuedBuffers);
+        status_t result = remote()->transact(SET_MAX_DEQUEUED_BUFFER_COUNT,
+                data, &reply);
         if (result != NO_ERROR) {
             return result;
         }
@@ -95,12 +102,24 @@
         return result;
     }
 
-    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, bool async,
-            uint32_t width, uint32_t height, PixelFormat format,
-            uint32_t usage) {
+    virtual status_t setAsyncMode(bool async) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(async);
+        status_t result = remote()->transact(SET_ASYNC_MODE,
+                data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readInt32();
+        return result;
+    }
+
+    virtual status_t dequeueBuffer(int *buf, sp<Fence>* fence, uint32_t width,
+            uint32_t height, PixelFormat format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(async));
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
@@ -190,12 +209,17 @@
         return result;
     }
 
-    virtual void cancelBuffer(int buf, const sp<Fence>& fence) {
+    virtual status_t cancelBuffer(int buf, const sp<Fence>& fence) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
         data.writeInt32(buf);
         data.write(*fence.get());
-        remote()->transact(CANCEL_BUFFER, data, &reply);
+        status_t result = remote()->transact(CANCEL_BUFFER, data, &reply);
+        if (result != NO_ERROR) {
+            return result;
+        }
+        result = reply.readInt32();
+        return result;
     }
 
     virtual int query(int what, int* value) {
@@ -260,11 +284,10 @@
         return result;
     }
 
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage) {
         Parcel data, reply;
         data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
-        data.writeInt32(static_cast<int32_t>(async));
         data.writeUint32(width);
         data.writeUint32(height);
         data.writeInt32(static_cast<int32_t>(format));
@@ -308,6 +331,93 @@
         }
         return reply.readString8();
     }
+
+    virtual uint64_t getNextFrameNumber() const {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_NEXT_FRAME_NUMBER, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getNextFrameNumber failed to transact: %d", result);
+            return 0;
+        }
+        uint64_t frameNumber = reply.readUint64();
+        return frameNumber;
+    }
+
+    virtual status_t setSharedBufferMode(bool sharedBufferMode) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(sharedBufferMode);
+        status_t result = remote()->transact(SET_SHARED_BUFFER_MODE, data,
+                &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
+
+    virtual status_t setAutoRefresh(bool autoRefresh) {
+        Parcel data, reply;
+        data.writeInterfaceToken(
+                IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt32(autoRefresh);
+        status_t result = remote()->transact(SET_AUTO_REFRESH, data, &reply);
+        if (result == NO_ERROR) {
+            result = reply.readInt32();
+        }
+        return result;
+    }
+
+    virtual status_t setDequeueTimeout(nsecs_t timeout) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        data.writeInt64(timeout);
+        status_t result = remote()->transact(SET_DEQUEUE_TIMEOUT, data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("setDequeueTimeout failed to transact: %d", result);
+            return result;
+        }
+        return reply.readInt32();
+    }
+
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]) override {
+        Parcel data, reply;
+        data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor());
+        status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER, data,
+                &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result != NO_ERROR) {
+            return result;
+        }
+        bool hasBuffer = reply.readBool();
+        sp<GraphicBuffer> buffer;
+        if (hasBuffer) {
+            buffer = new GraphicBuffer();
+            result = reply.read(*buffer);
+            if (result == NO_ERROR) {
+                result = reply.read(outTransformMatrix, sizeof(float) * 16);
+            }
+        }
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to read buffer: %d", result);
+            return result;
+        }
+        sp<Fence> fence(new Fence);
+        result = reply.read(*fence);
+        if (result != NO_ERROR) {
+            ALOGE("getLastQueuedBuffer failed to read fence: %d", result);
+            return result;
+        }
+        *outBuffer = buffer;
+        *outFence = fence;
+        return result;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -334,24 +444,30 @@
             reply->writeInt32(result);
             return NO_ERROR;
         }
-        case SET_BUFFER_COUNT: {
+        case SET_MAX_DEQUEUED_BUFFER_COUNT: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            int bufferCount = data.readInt32();
-            int result = setBufferCount(bufferCount);
+            int maxDequeuedBuffers = data.readInt32();
+            int result = setMaxDequeuedBufferCount(maxDequeuedBuffers);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_ASYNC_MODE: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            bool async = data.readInt32();
+            int result = setAsyncMode(async);
             reply->writeInt32(result);
             return NO_ERROR;
         }
         case DEQUEUE_BUFFER: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool async = static_cast<bool>(data.readInt32());
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
             int buf = 0;
             sp<Fence> fence;
-            int result = dequeueBuffer(&buf, &fence, async, width, height,
-                    format, usage);
+            int result = dequeueBuffer(&buf, &fence, width, height, format,
+                    usage);
             reply->writeInt32(buf);
             reply->writeInt32(fence != NULL);
             if (fence != NULL) {
@@ -412,7 +528,8 @@
             int buf = data.readInt32();
             sp<Fence> fence = new Fence();
             data.read(*fence.get());
-            cancelBuffer(buf, fence);
+            status_t result = cancelBuffer(buf, fence);
+            reply->writeInt32(result);
             return NO_ERROR;
         }
         case QUERY: {
@@ -459,12 +576,11 @@
         }
         case ALLOCATE_BUFFERS: {
             CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
-            bool async = static_cast<bool>(data.readInt32());
             uint32_t width = data.readUint32();
             uint32_t height = data.readUint32();
             PixelFormat format = static_cast<PixelFormat>(data.readInt32());
             uint32_t usage = data.readUint32();
-            allocateBuffers(async, width, height, format, usage);
+            allocateBuffers(width, height, format, usage);
             return NO_ERROR;
         }
         case ALLOW_ALLOCATION: {
@@ -486,6 +602,63 @@
             reply->writeString8(getConsumerName());
             return NO_ERROR;
         }
+        case GET_NEXT_FRAME_NUMBER: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            uint64_t frameNumber = getNextFrameNumber();
+            reply->writeUint64(frameNumber);
+            return NO_ERROR;
+        }
+        case SET_SHARED_BUFFER_MODE: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            bool sharedBufferMode = data.readInt32();
+            status_t result = setSharedBufferMode(sharedBufferMode);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_AUTO_REFRESH: {
+            CHECK_INTERFACE(IGraphicBuffer, data, reply);
+            bool autoRefresh = data.readInt32();
+            status_t result = setAutoRefresh(autoRefresh);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case SET_DEQUEUE_TIMEOUT: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            nsecs_t timeout = data.readInt64();
+            status_t result = setDequeueTimeout(timeout);
+            reply->writeInt32(result);
+            return NO_ERROR;
+        }
+        case GET_LAST_QUEUED_BUFFER: {
+            CHECK_INTERFACE(IGraphicBufferProducer, data, reply);
+            sp<GraphicBuffer> buffer(nullptr);
+            sp<Fence> fence(Fence::NO_FENCE);
+            float transform[16] = {};
+            status_t result = getLastQueuedBuffer(&buffer, &fence, transform);
+            reply->writeInt32(result);
+            if (result != NO_ERROR) {
+                return result;
+            }
+            if (!buffer.get()) {
+                reply->writeBool(false);
+            } else {
+                reply->writeBool(true);
+                result = reply->write(*buffer);
+                if (result == NO_ERROR) {
+                    reply->write(transform, sizeof(float) * 16);
+                }
+            }
+            if (result != NO_ERROR) {
+                ALOGE("getLastQueuedBuffer failed to write buffer: %d", result);
+                return result;
+            }
+            result = reply->write(*fence);
+            if (result != NO_ERROR) {
+                ALOGE("getLastQueuedBuffer failed to write fence: %d", result);
+                return result;
+            }
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
@@ -504,7 +677,6 @@
          + sizeof(scalingMode)
          + sizeof(transform)
          + sizeof(stickyTransform)
-         + sizeof(async)
          + fence->getFlattenedSize()
          + surfaceDamage.getFlattenedSize();
 }
@@ -526,7 +698,6 @@
     FlattenableUtils::write(buffer, size, scalingMode);
     FlattenableUtils::write(buffer, size, transform);
     FlattenableUtils::write(buffer, size, stickyTransform);
-    FlattenableUtils::write(buffer, size, async);
     status_t result = fence->flatten(buffer, size, fds, count);
     if (result != NO_ERROR) {
         return result;
@@ -544,8 +715,7 @@
             + sizeof(crop)
             + sizeof(scalingMode)
             + sizeof(transform)
-            + sizeof(stickyTransform)
-            + sizeof(async);
+            + sizeof(stickyTransform);
 
     if (size < minNeeded) {
         return NO_MEMORY;
@@ -558,7 +728,6 @@
     FlattenableUtils::read(buffer, size, scalingMode);
     FlattenableUtils::read(buffer, size, transform);
     FlattenableUtils::read(buffer, size, stickyTransform);
-    FlattenableUtils::read(buffer, size, async);
 
     fence = new Fence();
     status_t result = fence->unflatten(buffer, size, fds, count);
diff --git a/libs/gui/ISensorServer.cpp b/libs/gui/ISensorServer.cpp
index f581b5c..3a4c7e4 100644
--- a/libs/gui/ISensorServer.cpp
+++ b/libs/gui/ISensorServer.cpp
@@ -35,7 +35,8 @@
 enum {
     GET_SENSOR_LIST = IBinder::FIRST_CALL_TRANSACTION,
     CREATE_SENSOR_EVENT_CONNECTION,
-    ENABLE_DATA_INJECTION
+    ENABLE_DATA_INJECTION,
+    GET_DYNAMIC_SENSOR_LIST,
 };
 
 class BpSensorServer : public BpInterface<ISensorServer>
@@ -65,6 +66,23 @@
         return v;
     }
 
+    virtual Vector<Sensor> getDynamicSensorList(const String16& opPackageName)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISensorServer::getInterfaceDescriptor());
+        data.writeString16(opPackageName);
+        remote()->transact(GET_DYNAMIC_SENSOR_LIST, data, &reply);
+        Sensor s;
+        Vector<Sensor> v;
+        uint32_t n = reply.readUint32();
+        v.setCapacity(n);
+        while (n--) {
+            reply.read(s);
+            v.add(s);
+        }
+        return v;
+    }
+
     virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
              int mode, const String16& opPackageName)
     {
@@ -124,6 +142,17 @@
             reply->writeInt32(static_cast<int32_t>(ret));
             return NO_ERROR;
         }
+        case GET_DYNAMIC_SENSOR_LIST: {
+            CHECK_INTERFACE(ISensorServer, data, reply);
+            const String16& opPackageName = data.readString16();
+            Vector<Sensor> v(getDynamicSensorList(opPackageName));
+            size_t n = v.size();
+            reply->writeUint32(static_cast<uint32_t>(n));
+            for (size_t i = 0; i < n; i++) {
+                reply->write(v[i]);
+            }
+            return NO_ERROR;
+        }
     }
     return BBinder::onTransact(code, data, reply, flags);
 }
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 78886d5..a8b4fa8 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -34,6 +34,7 @@
 
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayStatInfo.h>
+#include <ui/HdrCapabilities.h>
 
 #include <utils/Log.h>
 
@@ -282,6 +283,28 @@
         reply.read(*outStats);
         return reply.readInt32();
     }
+
+    virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+            HdrCapabilities* outCapabilities) const {
+        Parcel data, reply;
+        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
+        status_t result = data.writeStrongBinder(display);
+        if (result != NO_ERROR) {
+            ALOGE("getHdrCapabilities failed to writeStrongBinder: %d", result);
+            return result;
+        }
+        result = remote()->transact(BnSurfaceComposer::GET_HDR_CAPABILITIES,
+                data, &reply);
+        if (result != NO_ERROR) {
+            ALOGE("getHdrCapabilities failed to transact: %d", result);
+            return result;
+        }
+        result = reply.readInt32();
+        if (result == NO_ERROR) {
+            result = reply.readParcelable(outCapabilities);
+        }
+        return result;
+    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this
@@ -353,7 +376,7 @@
             sp<IBinder> display = data.readStrongBinder();
             sp<IGraphicBufferProducer> producer =
                     interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
-            Rect sourceCrop;
+            Rect sourceCrop(Rect::EMPTY_RECT);
             data.read(sourceCrop);
             uint32_t reqWidth = data.readUint32();
             uint32_t reqHeight = data.readUint32();
@@ -467,6 +490,23 @@
             setPowerMode(display, mode);
             return NO_ERROR;
         }
+        case GET_HDR_CAPABILITIES: {
+            CHECK_INTERFACE(ISurfaceComposer, data, reply);
+            sp<IBinder> display = nullptr;
+            status_t result = data.readStrongBinder(&display);
+            if (result != NO_ERROR) {
+                ALOGE("getHdrCapabilities failed to readStrongBinder: %d",
+                        result);
+                return result;
+            }
+            HdrCapabilities capabilities;
+            result = getHdrCapabilities(display, &capabilities);
+            reply->writeInt32(result);
+            if (result == NO_ERROR) {
+                reply->writeParcelable(capabilities);
+            }
+            return NO_ERROR;
+        }
         default: {
             return BBinder::onTransact(code, data, reply, flags);
         }
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 00323dc..d1c576e 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -38,6 +38,10 @@
     *reinterpret_cast<layer_state_t::matrix22_t *>(
             output.writeInplace(sizeof(layer_state_t::matrix22_t))) = matrix;
     output.write(crop);
+    output.write(finalCrop);
+    output.writeStrongBinder(handle);
+    output.writeUint64(frameNumber);
+    output.writeInt32(overrideScalingMode);
     output.write(transparentRegion);
     return NO_ERROR;
 }
@@ -62,6 +66,10 @@
         return BAD_VALUE;
     }
     input.read(crop);
+    input.read(finalCrop);
+    handle = input.readStrongBinder();
+    frameNumber = input.readUint64();
+    overrideScalingMode = input.readInt32();
     input.read(transparentRegion);
     return NO_ERROR;
 }
@@ -77,6 +85,16 @@
 }
 
 
+DisplayState::DisplayState() :
+    what(0),
+    layerStack(0),
+    orientation(eOrientationDefault),
+    viewport(Rect::EMPTY_RECT),
+    frame(Rect::EMPTY_RECT),
+    width(0),
+    height(0) {
+}
+
 status_t DisplayState::write(Parcel& output) const {
     output.writeStrongBinder(token);
     output.writeStrongBinder(IInterface::asBinder(surface));
diff --git a/libs/gui/Sensor.cpp b/libs/gui/Sensor.cpp
index 235cbbd..cc865d1 100644
--- a/libs/gui/Sensor.cpp
+++ b/libs/gui/Sensor.cpp
@@ -14,68 +14,70 @@
  * limitations under the License.
  */
 
+
+#include <binder/AppOpsManager.h>
+#include <binder/IServiceManager.h>
+#include <gui/Sensor.h>
+#include <hardware/sensors.h>
+#include <log/log.h>
+#include <utils/Errors.h>
+#include <utils/String8.h>
+#include <utils/Flattenable.h>
+
 #include <inttypes.h>
 #include <stdint.h>
 #include <sys/types.h>
 #include <sys/limits.h>
 
-#include <utils/Errors.h>
-#include <utils/String8.h>
-#include <utils/Flattenable.h>
-
-#include <hardware/sensors.h>
-
-#include <binder/AppOpsManager.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Sensor.h>
-#include <log/log.h>
-
 // ----------------------------------------------------------------------------
 namespace android {
 // ----------------------------------------------------------------------------
 
-Sensor::Sensor()
-    : mHandle(0), mType(0),
-      mMinValue(0), mMaxValue(0), mResolution(0),
-      mPower(0), mMinDelay(0), mFifoReservedEventCount(0), mFifoMaxEventCount(0),
-      mMaxDelay(0), mFlags(0)
-{
+Sensor::Sensor(const char * name) :
+        mName(name), mHandle(0), mType(0),
+        mMinValue(0), mMaxValue(0), mResolution(0),
+        mPower(0), mMinDelay(0), mVersion(0), mFifoReservedEventCount(0),
+        mFifoMaxEventCount(0), mRequiredAppOp(0),
+        mMaxDelay(0), mFlags(0) {
 }
 
-Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion)
-{
-    mName = hwSensor->name;
-    mVendor = hwSensor->vendor;
-    mVersion = hwSensor->version;
-    mHandle = hwSensor->handle;
-    mType = hwSensor->type;
+Sensor::Sensor(struct sensor_t const* hwSensor, int halVersion) :
+        Sensor(*hwSensor, uuid_t(), halVersion) {
+}
+
+Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersion) {
+    mName = hwSensor.name;
+    mVendor = hwSensor.vendor;
+    mVersion = hwSensor.version;
+    mHandle = hwSensor.handle;
+    mType = hwSensor.type;
     mMinValue = 0;                      // FIXME: minValue
-    mMaxValue = hwSensor->maxRange;     // FIXME: maxValue
-    mResolution = hwSensor->resolution;
-    mPower = hwSensor->power;
-    mMinDelay = hwSensor->minDelay;
+    mMaxValue = hwSensor.maxRange;     // FIXME: maxValue
+    mResolution = hwSensor.resolution;
+    mPower = hwSensor.power;
+    mMinDelay = hwSensor.minDelay;
     mFlags = 0;
+    mUuid = uuid;
 
     // Set fifo event count zero for older devices which do not support batching. Fused
     // sensors also have their fifo counts set to zero.
     if (halVersion > SENSORS_DEVICE_API_VERSION_1_0) {
-        mFifoReservedEventCount = hwSensor->fifoReservedEventCount;
-        mFifoMaxEventCount = hwSensor->fifoMaxEventCount;
+        mFifoReservedEventCount = hwSensor.fifoReservedEventCount;
+        mFifoMaxEventCount = hwSensor.fifoMaxEventCount;
     } else {
         mFifoReservedEventCount = 0;
         mFifoMaxEventCount = 0;
     }
 
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-        if (hwSensor->maxDelay > INT_MAX) {
+        if (hwSensor.maxDelay > INT_MAX) {
             // Max delay is declared as a 64 bit integer for 64 bit architectures. But it should
             // always fit in a 32 bit integer, log error and cap it to INT_MAX.
             ALOGE("Sensor maxDelay overflow error %s %" PRId64, mName.string(),
-                  static_cast<int64_t>(hwSensor->maxDelay));
+                  static_cast<int64_t>(hwSensor.maxDelay));
             mMaxDelay = INT_MAX;
         } else {
-            mMaxDelay = static_cast<int32_t>(hwSensor->maxDelay);
+            mMaxDelay = static_cast<int32_t>(hwSensor.maxDelay);
         }
     } else {
         // For older hals set maxDelay to 0.
@@ -187,7 +189,7 @@
         if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
             mFlags |= SENSOR_FLAG_WAKE_UP;
         }
-         break;
+        break;
     case SENSOR_TYPE_WAKE_GESTURE:
         mStringType = SENSOR_STRING_TYPE_WAKE_GESTURE;
         mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
@@ -216,13 +218,39 @@
             mFlags |= SENSOR_FLAG_WAKE_UP;
         }
         break;
+    case SENSOR_TYPE_DYNAMIC_SENSOR_META:
+        mStringType = SENSOR_STRING_TYPE_DYNAMIC_SENSOR_META;
+        mFlags = SENSOR_FLAG_SPECIAL_REPORTING_MODE; // special trigger and non-wake up
+        break;
+    case SENSOR_TYPE_POSE_6DOF:
+        mStringType = SENSOR_STRING_TYPE_POSE_6DOF;
+        mFlags |= SENSOR_FLAG_CONTINUOUS_MODE;
+        break;
+    case SENSOR_TYPE_STATIONARY_DETECT:
+        mStringType = SENSOR_STRING_TYPE_STATIONARY_DETECT;
+        mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+        if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+            mFlags |= SENSOR_FLAG_WAKE_UP;
+        }
+        break;
+    case SENSOR_TYPE_MOTION_DETECT:
+        mStringType = SENSOR_STRING_TYPE_MOTION_DETECT;
+        mFlags |= SENSOR_FLAG_ONE_SHOT_MODE;
+        if (halVersion < SENSORS_DEVICE_API_VERSION_1_3) {
+            mFlags |= SENSOR_FLAG_WAKE_UP;
+        }
+        break;
+    case SENSOR_TYPE_HEART_BEAT:
+        mStringType = SENSOR_STRING_TYPE_HEART_BEAT;
+        mFlags |= SENSOR_FLAG_SPECIAL_REPORTING_MODE;
+        break;
     default:
         // Only pipe the stringType, requiredPermission and flags for custom sensors.
-        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->stringType) {
-            mStringType = hwSensor->stringType;
+        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.stringType) {
+            mStringType = hwSensor.stringType;
         }
-        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor->requiredPermission) {
-            mRequiredPermission = hwSensor->requiredPermission;
+        if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.requiredPermission) {
+            mRequiredPermission = hwSensor.requiredPermission;
             if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) {
                 AppOpsManager appOps;
                 mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS));
@@ -230,7 +258,7 @@
         }
 
         if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-            mFlags = static_cast<uint32_t>(hwSensor->flags);
+            mFlags = static_cast<uint32_t>(hwSensor.flags);
         } else {
             // This is an OEM defined sensor on an older HAL. Use minDelay to determine the
             // reporting mode of the sensor.
@@ -245,26 +273,28 @@
         break;
     }
 
-    // Set DATA_INJECTION flag here. Defined in HAL 1_4.
-    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
-        mFlags |= (hwSensor->flags & DATA_INJECTION_MASK);
+    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
+        // Wake-up flag of HAL 1.3 and above is set here
+        mFlags |= (hwSensor.flags & SENSOR_FLAG_WAKE_UP);
+
+        // Log error if the reporting mode is not as expected, but respect HAL setting.
+        int actualReportingMode = (hwSensor.flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+        int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
+        if (actualReportingMode != expectedReportingMode) {
+            ALOGE("Reporting Mode incorrect: sensor %s handle=%#010" PRIx32 " type=%" PRId32 " "
+                   "actual=%d expected=%d",
+                   mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
+        }
     }
 
-    // For the newer HALs log errors if reporting mask flags are set incorrectly.
+    // Feature flags
+    // Set DYNAMIC_SENSOR_MASK and ADDITIONAL_INFO_MASK flag here. Compatible with HAL 1_3.
     if (halVersion >= SENSORS_DEVICE_API_VERSION_1_3) {
-        // Wake-up flag is set here.
-        mFlags |= (hwSensor->flags & SENSOR_FLAG_WAKE_UP);
-        if (mFlags != hwSensor->flags) {
-            int actualReportingMode =
-                 (hwSensor->flags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
-            int expectedReportingMode = (mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT;
-            if (actualReportingMode != expectedReportingMode) {
-                ALOGE("Reporting Mode incorrect: sensor %s handle=%d type=%d "
-                       "actual=%d expected=%d",
-                       mName.string(), mHandle, mType, actualReportingMode, expectedReportingMode);
-            }
-
-        }
+        mFlags |= (hwSensor.flags & (DYNAMIC_SENSOR_MASK | ADDITIONAL_INFO_MASK));
+    }
+    // Set DATA_INJECTION flag here. Defined in HAL 1_4.
+    if (halVersion >= SENSORS_DEVICE_API_VERSION_1_4) {
+        mFlags |= (hwSensor.flags & DATA_INJECTION_MASK);
     }
 
     if (mRequiredPermission.length() > 0) {
@@ -279,8 +309,7 @@
     }
 }
 
-Sensor::~Sensor()
-{
+Sensor::~Sensor() {
 }
 
 const String8& Sensor::getName() const {
@@ -360,20 +389,32 @@
 }
 
 bool Sensor::isWakeUpSensor() const {
-    return mFlags & SENSOR_FLAG_WAKE_UP;
+    return (mFlags & SENSOR_FLAG_WAKE_UP) != 0;
+}
+
+bool Sensor::isDynamicSensor() const {
+    return (mFlags & SENSOR_FLAG_DYNAMIC_SENSOR) != 0;
+}
+
+bool Sensor::hasAdditionalInfo() const {
+    return (mFlags & SENSOR_FLAG_ADDITIONAL_INFO) != 0;
 }
 
 int32_t Sensor::getReportingMode() const {
     return ((mFlags & REPORTING_MODE_MASK) >> REPORTING_MODE_SHIFT);
 }
 
-size_t Sensor::getFlattenedSize() const
-{
+const Sensor::uuid_t& Sensor::getUuid() const {
+    return mUuid;
+}
+
+size_t Sensor::getFlattenedSize() const {
     size_t fixedSize =
-            sizeof(int32_t) * 3 +
-            sizeof(float) * 4 +
-            sizeof(int32_t) * 6 +
-            sizeof(bool);
+            sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) +
+            sizeof(mMinValue) + sizeof(mMaxValue) + sizeof(mResolution) +
+            sizeof(mPower) + sizeof(mMinDelay) + sizeof(mFifoMaxEventCount) +
+            sizeof(mFifoMaxEventCount) + sizeof(mRequiredPermissionRuntime) +
+            sizeof(mRequiredAppOp) + sizeof(mMaxDelay) + sizeof(mFlags) + sizeof(mUuid);
 
     size_t variableSize =
             sizeof(uint32_t) + FlattenableUtils::align<4>(mName.length()) +
@@ -407,6 +448,7 @@
     FlattenableUtils::write(buffer, size, mRequiredAppOp);
     FlattenableUtils::write(buffer, size, mMaxDelay);
     FlattenableUtils::write(buffer, size, mFlags);
+    FlattenableUtils::write(buffer, size, mUuid);
     return NO_ERROR;
 }
 
@@ -418,11 +460,11 @@
         return NO_MEMORY;
     }
 
-    size_t fixedSize =
-            sizeof(int32_t) * 3 +
-            sizeof(float) * 4 +
-            sizeof(int32_t) * 5;
-    if (size < fixedSize) {
+    size_t fixedSize1 =
+            sizeof(mVersion) + sizeof(mHandle) + sizeof(mType) + sizeof(mMinValue) +
+            sizeof(mMaxValue) + sizeof(mResolution) + sizeof(mPower) + sizeof(mMinDelay) +
+            sizeof(mFifoMaxEventCount) + sizeof(mFifoMaxEventCount);
+    if (size < fixedSize1) {
         return NO_MEMORY;
     }
 
@@ -443,10 +485,19 @@
     if (!unflattenString8(buffer, size, mRequiredPermission)) {
         return NO_MEMORY;
     }
+
+    size_t fixedSize2 =
+            sizeof(mRequiredPermissionRuntime) + sizeof(mRequiredAppOp) + sizeof(mMaxDelay) +
+            sizeof(mFlags) + sizeof(mUuid);
+    if (size < fixedSize2) {
+        return NO_MEMORY;
+    }
+
     FlattenableUtils::read(buffer, size, mRequiredPermissionRuntime);
     FlattenableUtils::read(buffer, size, mRequiredAppOp);
     FlattenableUtils::read(buffer, size, mMaxDelay);
     FlattenableUtils::read(buffer, size, mFlags);
+    FlattenableUtils::read(buffer, size, mUuid);
     return NO_ERROR;
 }
 
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index 4b7986e..6d69839 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -125,11 +125,16 @@
 }
 
 status_t SensorEventQueue::enableSensor(Sensor const* sensor) const {
-    return mSensorEventConnection->enableDisable(sensor->getHandle(), true, 0, 0, false);
+    return enableSensor(sensor, SENSOR_DELAY_NORMAL);
+}
+
+status_t SensorEventQueue::enableSensor(Sensor const* sensor, int32_t samplingPeriodUs) const {
+    return mSensorEventConnection->enableDisable(sensor->getHandle(), true,
+                                                 us2ns(samplingPeriodUs), 0, 0);
 }
 
 status_t SensorEventQueue::disableSensor(Sensor const* sensor) const {
-    return mSensorEventConnection->enableDisable(sensor->getHandle(), false, 0, 0, false);
+    return mSensorEventConnection->enableDisable(sensor->getHandle(), false, 0, 0, 0);
 }
 
 status_t SensorEventQueue::enableSensor(int32_t handle, int32_t samplingPeriodUs,
diff --git a/libs/gui/SensorManager.cpp b/libs/gui/SensorManager.cpp
index 33608b5..225bfa8 100644
--- a/libs/gui/SensorManager.cpp
+++ b/libs/gui/SensorManager.cpp
@@ -89,19 +89,16 @@
 }
 
 SensorManager::SensorManager(const String16& opPackageName)
-    : mSensorList(0), mOpPackageName(opPackageName)
-{
+    : mSensorList(0), mOpPackageName(opPackageName) {
     // okay we're not locked here, but it's not needed during construction
     assertStateLocked();
 }
 
-SensorManager::~SensorManager()
-{
+SensorManager::~SensorManager() {
     free(mSensorList);
 }
 
-void SensorManager::sensorManagerDied()
-{
+void SensorManager::sensorManagerDied() {
     Mutex::Autolock _l(mLock);
     mSensorServer.clear();
     free(mSensorList);
@@ -109,7 +106,7 @@
     mSensors.clear();
 }
 
-status_t SensorManager::assertStateLocked() const {
+status_t SensorManager::assertStateLocked() {
     bool initSensorManager = false;
     if (mSensorServer == NULL) {
         initSensorManager = true;
@@ -136,13 +133,13 @@
         }
 
         class DeathObserver : public IBinder::DeathRecipient {
-            SensorManager& mSensorManger;
+            SensorManager& mSensorManager;
             virtual void binderDied(const wp<IBinder>& who) {
                 ALOGW("sensorservice died [%p]", who.unsafe_get());
-                mSensorManger.sensorManagerDied();
+                mSensorManager.sensorManagerDied();
             }
         public:
-            DeathObserver(SensorManager& mgr) : mSensorManger(mgr) { }
+            DeathObserver(SensorManager& mgr) : mSensorManager(mgr) { }
         };
 
         LOG_ALWAYS_FATAL_IF(mSensorServer.get() == NULL, "getService(SensorService) NULL");
@@ -164,8 +161,7 @@
     return NO_ERROR;
 }
 
-ssize_t SensorManager::getSensorList(Sensor const* const** list) const
-{
+ssize_t SensorManager::getSensorList(Sensor const* const** list) {
     Mutex::Autolock _l(mLock);
     status_t err = assertStateLocked();
     if (err < 0) {
@@ -175,6 +171,19 @@
     return static_cast<ssize_t>(mSensors.size());
 }
 
+ssize_t SensorManager::getDynamicSensorList(Vector<Sensor> & dynamicSensors) {
+    Mutex::Autolock _l(mLock);
+    status_t err = assertStateLocked();
+    if (err < 0) {
+        return static_cast<ssize_t>(err);
+    }
+
+    dynamicSensors = mSensorServer->getDynamicSensorList(mOpPackageName);
+    size_t count = dynamicSensors.size();
+
+    return static_cast<ssize_t>(count);
+}
+
 Sensor const* SensorManager::getDefaultSensor(int type)
 {
     Mutex::Autolock _l(mLock);
diff --git a/libs/gui/StreamSplitter.cpp b/libs/gui/StreamSplitter.cpp
index 43f9214..bafe947 100644
--- a/libs/gui/StreamSplitter.cpp
+++ b/libs/gui/StreamSplitter.cpp
@@ -132,7 +132,7 @@
     ALOGV("acquired buffer %#" PRIx64 " from input",
             bufferItem.mGraphicBuffer->getId());
 
-    status = mInput->detachBuffer(bufferItem.mBuf);
+    status = mInput->detachBuffer(bufferItem.mSlot);
     LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
             "detaching buffer from input failed (%d)", status);
 
@@ -144,8 +144,7 @@
             bufferItem.mTimestamp, bufferItem.mIsAutoTimestamp,
             bufferItem.mDataSpace, bufferItem.mCrop,
             static_cast<int32_t>(bufferItem.mScalingMode),
-            bufferItem.mTransform, bufferItem.mIsDroppable,
-            bufferItem.mFence);
+            bufferItem.mTransform, bufferItem.mFence);
 
     // Attach and queue the buffer to each of the outputs
     Vector<sp<IGraphicBufferProducer> >::iterator output = mOutputs.begin();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 4b76f98..6811269 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -43,7 +43,12 @@
         const sp<IGraphicBufferProducer>& bufferProducer,
         bool controlledByApp)
     : mGraphicBufferProducer(bufferProducer),
-      mGenerationNumber(0)
+      mCrop(Rect::EMPTY_RECT),
+      mGenerationNumber(0),
+      mSharedBufferMode(false),
+      mAutoRefresh(false),
+      mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
+      mSharedBufferHasBeenQueued(false)
 {
     // Initialize the ANativeWindow function pointers.
     ANativeWindow::setSwapInterval  = hook_setSwapInterval;
@@ -67,7 +72,6 @@
     mReqUsage = 0;
     mTimestamp = NATIVE_WINDOW_TIMESTAMP_AUTO;
     mDataSpace = HAL_DATASPACE_UNKNOWN;
-    mCrop.clear();
     mScalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
     mTransform = 0;
     mStickyTransform = 0;
@@ -99,8 +103,8 @@
 void Surface::allocateBuffers() {
     uint32_t reqWidth = mReqWidth ? mReqWidth : mUserWidth;
     uint32_t reqHeight = mReqHeight ? mReqHeight : mUserHeight;
-    mGraphicBufferProducer->allocateBuffers(mSwapIntervalZero, reqWidth,
-            reqHeight, mReqFormat, mReqUsage);
+    mGraphicBufferProducer->allocateBuffers(reqWidth, reqHeight,
+            mReqFormat, mReqUsage);
 }
 
 status_t Surface::setGenerationNumber(uint32_t generation) {
@@ -111,10 +115,24 @@
     return result;
 }
 
+uint64_t Surface::getNextFrameNumber() const {
+    return mGraphicBufferProducer->getNextFrameNumber();
+}
+
 String8 Surface::getConsumerName() const {
     return mGraphicBufferProducer->getConsumerName();
 }
 
+status_t Surface::setDequeueTimeout(nsecs_t timeout) {
+    return mGraphicBufferProducer->setDequeueTimeout(timeout);
+}
+
+status_t Surface::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    return mGraphicBufferProducer->getLastQueuedBuffer(outBuffer, outFence,
+            outTransformMatrix);
+}
+
 int Surface::hook_setSwapInterval(ANativeWindow* window, int interval) {
     Surface* c = getSelf(window);
     return c->setSwapInterval(interval);
@@ -184,7 +202,9 @@
     va_list args;
     va_start(args, operation);
     Surface* c = getSelf(window);
-    return c->perform(operation, args);
+    int result = c->perform(operation, args);
+    va_end(args);
+    return result;
 }
 
 int Surface::setSwapInterval(int interval) {
@@ -200,6 +220,7 @@
         interval = maxSwapInterval;
 
     mSwapIntervalZero = (interval == 0);
+    mGraphicBufferProducer->setAsyncMode(mSwapIntervalZero);
 
     return NO_ERROR;
 }
@@ -210,7 +231,6 @@
 
     uint32_t reqWidth;
     uint32_t reqHeight;
-    bool swapIntervalZero;
     PixelFormat reqFormat;
     uint32_t reqUsage;
 
@@ -220,20 +240,29 @@
         reqWidth = mReqWidth ? mReqWidth : mUserWidth;
         reqHeight = mReqHeight ? mReqHeight : mUserHeight;
 
-        swapIntervalZero = mSwapIntervalZero;
         reqFormat = mReqFormat;
         reqUsage = mReqUsage;
+
+        if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot !=
+                BufferItem::INVALID_BUFFER_SLOT) {
+            sp<GraphicBuffer>& gbuf(mSlots[mSharedBufferSlot].buffer);
+            if (gbuf != NULL) {
+                *buffer = gbuf.get();
+                *fenceFd = -1;
+                return OK;
+            }
+        }
     } // Drop the lock so that we can still touch the Surface while blocking in IGBP::dequeueBuffer
 
     int buf = -1;
     sp<Fence> fence;
-    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence, swapIntervalZero,
+    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
             reqWidth, reqHeight, reqFormat, reqUsage);
 
     if (result < 0) {
-        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer(%d, %d, %d, %d, %d)"
-             "failed: %d", swapIntervalZero, reqWidth, reqHeight, reqFormat,
-             reqUsage, result);
+        ALOGV("dequeueBuffer: IGraphicBufferProducer::dequeueBuffer"
+                "(%d, %d, %d, %d) failed: %d", reqWidth, reqHeight, reqFormat,
+                reqUsage, result);
         return result;
     }
 
@@ -270,6 +299,15 @@
     }
 
     *buffer = gbuf.get();
+
+    if (mSharedBufferMode && mAutoRefresh) {
+        mSharedBufferSlot = buf;
+        mSharedBufferHasBeenQueued = false;
+    } else if (mSharedBufferSlot == buf) {
+        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
+        mSharedBufferHasBeenQueued = false;
+    }
+
     return OK;
 }
 
@@ -285,8 +323,19 @@
         }
         return i;
     }
+    if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+        return OK;
+    }
     sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
     mGraphicBufferProducer->cancelBuffer(i, fence);
+
+    if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
+        mSharedBufferHasBeenQueued = true;
+    }
+
     return OK;
 }
 
@@ -314,6 +363,7 @@
     Mutex::Autolock lock(mMutex);
     int64_t timestamp;
     bool isAutoTimestamp = false;
+
     if (mTimestamp == NATIVE_WINDOW_TIMESTAMP_AUTO) {
         timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
         isAutoTimestamp = true;
@@ -329,17 +379,23 @@
         }
         return i;
     }
+    if (mSharedBufferSlot == i && mSharedBufferHasBeenQueued) {
+        if (fenceFd >= 0) {
+            close(fenceFd);
+        }
+        return OK;
+    }
 
 
     // Make sure the crop rectangle is entirely inside the buffer.
-    Rect crop;
+    Rect crop(Rect::EMPTY_RECT);
     mCrop.intersect(Rect(buffer->width, buffer->height), &crop);
 
     sp<Fence> fence(fenceFd >= 0 ? new Fence(fenceFd) : Fence::NO_FENCE);
     IGraphicBufferProducer::QueueBufferOutput output;
     IGraphicBufferProducer::QueueBufferInput input(timestamp, isAutoTimestamp,
             mDataSpace, crop, mScalingMode, mTransform ^ mStickyTransform,
-            mSwapIntervalZero, fence, mStickyTransform);
+            fence, mStickyTransform);
 
     if (mConnectedToCpu || mDirtyRegion.bounds() == Rect::INVALID_RECT) {
         input.setSurfaceDamage(Region::INVALID_REGION);
@@ -408,6 +464,7 @@
     if (err != OK)  {
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
+
     uint32_t numPendingBuffers = 0;
     uint32_t hint = 0;
     output.deflate(&mDefaultWidth, &mDefaultHeight, &hint,
@@ -425,6 +482,12 @@
         mDirtyRegion = Region::INVALID_REGION;
     }
 
+    if (mSharedBufferMode && mAutoRefresh && mSharedBufferSlot == i) {
+        mSharedBufferHasBeenQueued = true;
+    }
+
+    mQueueBufferCondition.broadcast();
+
     return err;
 }
 
@@ -545,6 +608,12 @@
     case NATIVE_WINDOW_SET_SURFACE_DAMAGE:
         res = dispatchSetSurfaceDamage(args);
         break;
+    case NATIVE_WINDOW_SET_SHARED_BUFFER_MODE:
+        res = dispatchSetSharedBufferMode(args);
+        break;
+    case NATIVE_WINDOW_SET_AUTO_REFRESH:
+        res = dispatchSetAutoRefresh(args);
+        break;
     default:
         res = NAME_NOT_FOUND;
         break;
@@ -655,6 +724,16 @@
     return NO_ERROR;
 }
 
+int Surface::dispatchSetSharedBufferMode(va_list args) {
+    bool sharedBufferMode = va_arg(args, int);
+    return setSharedBufferMode(sharedBufferMode);
+}
+
+int Surface::dispatchSetAutoRefresh(va_list args) {
+    bool autoRefresh = va_arg(args, int);
+    return setAutoRefresh(autoRefresh);
+}
+
 int Surface::connect(int api) {
     static sp<IProducerListener> listener = new DummyProducerListener();
     return connect(api, listener);
@@ -696,6 +775,8 @@
     ATRACE_CALL();
     ALOGV("Surface::disconnect");
     Mutex::Autolock lock(mMutex);
+    mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
+    mSharedBufferHasBeenQueued = false;
     freeAllBuffers();
     int err = mGraphicBufferProducer->disconnect(api);
     if (!err) {
@@ -741,6 +822,13 @@
         *outFence = Fence::NO_FENCE;
     }
 
+    for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
+        if (mSlots[i].buffer != NULL &&
+                mSlots[i].buffer->handle == buffer->handle) {
+            mSlots[i].buffer = NULL;
+        }
+    }
+
     return NO_ERROR;
 }
 
@@ -771,6 +859,9 @@
 {
     ALOGV("Surface::setUsage");
     Mutex::Autolock lock(mMutex);
+    if (reqUsage != mReqUsage) {
+        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
+    }
     mReqUsage = reqUsage;
     return OK;
 }
@@ -779,7 +870,7 @@
 {
     ATRACE_CALL();
 
-    Rect realRect;
+    Rect realRect(Rect::EMPTY_RECT);
     if (rect == NULL || rect->isEmpty()) {
         realRect.clear();
     } else {
@@ -800,14 +891,77 @@
     ALOGV("Surface::setBufferCount");
     Mutex::Autolock lock(mMutex);
 
-    status_t err = mGraphicBufferProducer->setBufferCount(bufferCount);
-    ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
-            bufferCount, strerror(-err));
-
-    if (err == NO_ERROR) {
-        freeAllBuffers();
+    status_t err = NO_ERROR;
+    if (bufferCount == 0) {
+        err = mGraphicBufferProducer->setMaxDequeuedBufferCount(1);
+    } else {
+        int minUndequeuedBuffers = 0;
+        err = mGraphicBufferProducer->query(
+                NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBuffers);
+        if (err == NO_ERROR) {
+            err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
+                    bufferCount - minUndequeuedBuffers);
+        }
     }
 
+    ALOGE_IF(err, "IGraphicBufferProducer::setBufferCount(%d) returned %s",
+             bufferCount, strerror(-err));
+
+    return err;
+}
+
+int Surface::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
+    ATRACE_CALL();
+    ALOGV("Surface::setMaxDequeuedBufferCount");
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = mGraphicBufferProducer->setMaxDequeuedBufferCount(
+            maxDequeuedBuffers);
+    ALOGE_IF(err, "IGraphicBufferProducer::setMaxDequeuedBufferCount(%d) "
+            "returned %s", maxDequeuedBuffers, strerror(-err));
+
+    return err;
+}
+
+int Surface::setAsyncMode(bool async) {
+    ATRACE_CALL();
+    ALOGV("Surface::setAsyncMode");
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = mGraphicBufferProducer->setAsyncMode(async);
+    ALOGE_IF(err, "IGraphicBufferProducer::setAsyncMode(%d) returned %s",
+            async, strerror(-err));
+
+    return err;
+}
+
+int Surface::setSharedBufferMode(bool sharedBufferMode) {
+    ATRACE_CALL();
+    ALOGV("Surface::setSharedBufferMode (%d)", sharedBufferMode);
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = mGraphicBufferProducer->setSharedBufferMode(
+            sharedBufferMode);
+    if (err == NO_ERROR) {
+        mSharedBufferMode = sharedBufferMode;
+    }
+    ALOGE_IF(err, "IGraphicBufferProducer::setSharedBufferMode(%d) returned"
+            "%s", sharedBufferMode, strerror(-err));
+
+    return err;
+}
+
+int Surface::setAutoRefresh(bool autoRefresh) {
+    ATRACE_CALL();
+    ALOGV("Surface::setAutoRefresh (%d)", autoRefresh);
+    Mutex::Autolock lock(mMutex);
+
+    status_t err = mGraphicBufferProducer->setAutoRefresh(autoRefresh);
+    if (err == NO_ERROR) {
+        mAutoRefresh = autoRefresh;
+    }
+    ALOGE_IF(err, "IGraphicBufferProducer::setAutoRefresh(%d) returned %s",
+            autoRefresh, strerror(-err));
     return err;
 }
 
@@ -820,6 +974,9 @@
         return BAD_VALUE;
 
     Mutex::Autolock lock(mMutex);
+    if (width != mReqWidth || height != mReqHeight) {
+        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
+    }
     mReqWidth = width;
     mReqHeight = height;
     return NO_ERROR;
@@ -834,6 +991,9 @@
         return BAD_VALUE;
 
     Mutex::Autolock lock(mMutex);
+    if (width != mUserWidth || height != mUserHeight) {
+        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
+    }
     mUserWidth = width;
     mUserHeight = height;
     return NO_ERROR;
@@ -844,6 +1004,9 @@
     ALOGV("Surface::setBuffersFormat");
 
     Mutex::Autolock lock(mMutex);
+    if (format != mReqFormat) {
+        mSharedBufferSlot = BufferItem::INVALID_BUFFER_SLOT;
+    }
     mReqFormat = format;
     return NO_ERROR;
 }
@@ -857,6 +1020,7 @@
         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
             break;
         default:
             ALOGE("unknown scaling mode: %d", mode);
@@ -1103,4 +1267,66 @@
     return err;
 }
 
+bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
+    Mutex::Autolock lock(mMutex);
+    uint64_t currentFrame = mGraphicBufferProducer->getNextFrameNumber();
+    if (currentFrame > lastFrame) {
+      return true;
+    }
+    return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
+}
+
+namespace view {
+
+status_t Surface::writeToParcel(Parcel* parcel) const {
+    return writeToParcel(parcel, false);
+}
+
+status_t Surface::writeToParcel(Parcel* parcel, bool nameAlreadyWritten) const {
+    if (parcel == nullptr) return BAD_VALUE;
+
+    status_t res = OK;
+
+    if (!nameAlreadyWritten) res = parcel->writeString16(name);
+
+    if (res == OK) {
+        res = parcel->writeStrongBinder(
+                IGraphicBufferProducer::asBinder(graphicBufferProducer));
+    }
+    return res;
+}
+
+status_t Surface::readFromParcel(const Parcel* parcel) {
+    return readFromParcel(parcel, false);
+}
+
+status_t Surface::readFromParcel(const Parcel* parcel, bool nameAlreadyRead) {
+    if (parcel == nullptr) return BAD_VALUE;
+
+    if (!nameAlreadyRead) {
+        name = readMaybeEmptyString16(parcel);
+    }
+
+    sp<IBinder> binder;
+
+    status_t res = parcel->readStrongBinder(&binder);
+    if (res != OK) return res;
+
+    graphicBufferProducer = interface_cast<IGraphicBufferProducer>(binder);
+
+    return OK;
+}
+
+String16 Surface::readMaybeEmptyString16(const Parcel* parcel) {
+    size_t len;
+    const char16_t* str = parcel->readString16Inplace(&len);
+    if (str != nullptr) {
+        return String16(str, len);
+    } else {
+        return String16();
+    }
+}
+
+} // namespace view
+
 }; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 6ad47d8..e33cc37 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -156,8 +156,15 @@
     status_t setOrientation(int orientation);
     status_t setCrop(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
             const Rect& crop);
+    status_t setFinalCrop(const sp<SurfaceComposerClient>& client,
+            const sp<IBinder>& id, const Rect& crop);
     status_t setLayerStack(const sp<SurfaceComposerClient>& client,
             const sp<IBinder>& id, uint32_t layerStack);
+    status_t deferTransactionUntil(const sp<SurfaceComposerClient>& client,
+            const sp<IBinder>& id, const sp<IBinder>& handle,
+            uint64_t frameNumber);
+    status_t setOverrideScalingMode(const sp<SurfaceComposerClient>& client,
+            const sp<IBinder>& id, int32_t overrideScalingMode);
 
     void setDisplaySurface(const sp<IBinder>& token,
             const sp<IGraphicBufferProducer>& bufferProducer);
@@ -310,9 +317,9 @@
     layer_state_t* s = getLayerStateLocked(client, id);
     if (!s)
         return BAD_INDEX;
-    if (mask & layer_state_t::eLayerOpaque ||
-            mask & layer_state_t::eLayerHidden ||
-            mask & layer_state_t::eLayerSecure) {
+    if ((mask & layer_state_t::eLayerOpaque) ||
+            (mask & layer_state_t::eLayerHidden) ||
+            (mask & layer_state_t::eLayerSecure)) {
         s->what |= layer_state_t::eFlagsChanged;
     }
     s->flags &= ~mask;
@@ -383,6 +390,59 @@
     return NO_ERROR;
 }
 
+status_t Composer::setFinalCrop(const sp<SurfaceComposerClient>& client,
+        const sp<IBinder>& id, const Rect& crop) {
+    Mutex::Autolock _l(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s) {
+        return BAD_INDEX;
+    }
+    s->what |= layer_state_t::eFinalCropChanged;
+    s->finalCrop = crop;
+    return NO_ERROR;
+}
+
+status_t Composer::deferTransactionUntil(
+        const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
+        const sp<IBinder>& handle, uint64_t frameNumber) {
+    Mutex::Autolock lock(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s) {
+        return BAD_INDEX;
+    }
+    s->what |= layer_state_t::eDeferTransaction;
+    s->handle = handle;
+    s->frameNumber = frameNumber;
+    return NO_ERROR;
+}
+
+status_t Composer::setOverrideScalingMode(
+        const sp<SurfaceComposerClient>& client,
+        const sp<IBinder>& id, int32_t overrideScalingMode) {
+    Mutex::Autolock lock(mLock);
+    layer_state_t* s = getLayerStateLocked(client, id);
+    if (!s) {
+        return BAD_INDEX;
+    }
+
+    switch (overrideScalingMode) {
+        case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+        case NATIVE_WINDOW_SCALING_MODE_SCALE_CROP:
+        case NATIVE_WINDOW_SCALING_MODE_NO_SCALE_CROP:
+        case -1:
+            break;
+        default:
+            ALOGE("unknown scaling mode: %d",
+                    overrideScalingMode);
+            return BAD_VALUE;
+    }
+
+    s->what |= layer_state_t::eOverrideScalingModeChanged;
+    s->overrideScalingMode = overrideScalingMode;
+    return NO_ERROR;
+}
+
 // ---------------------------------------------------------------------------
 
 DisplayState& Composer::getDisplayStateLocked(const sp<IBinder>& token) {
@@ -562,6 +622,11 @@
     return getComposer().setCrop(this, id, crop);
 }
 
+status_t SurfaceComposerClient::setFinalCrop(const sp<IBinder>& id,
+        const Rect& crop) {
+    return getComposer().setFinalCrop(this, id, crop);
+}
+
 status_t SurfaceComposerClient::setPosition(const sp<IBinder>& id, float x, float y) {
     return getComposer().setPosition(this, id, x, y);
 }
@@ -609,6 +674,17 @@
     return getComposer().setMatrix(this, id, dsdx, dtdx, dsdy, dtdy);
 }
 
+status_t SurfaceComposerClient::deferTransactionUntil(const sp<IBinder>& id,
+        const sp<IBinder>& handle, uint64_t frameNumber) {
+    return getComposer().deferTransactionUntil(this, id, handle, frameNumber);
+}
+
+status_t SurfaceComposerClient::setOverrideScalingMode(
+        const sp<IBinder>& id, int32_t overrideScalingMode) {
+    return getComposer().setOverrideScalingMode(
+            this, id, overrideScalingMode);
+}
+
 // ----------------------------------------------------------------------------
 
 void SurfaceComposerClient::setDisplaySurface(const sp<IBinder>& token,
@@ -681,6 +757,12 @@
     return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
 }
 
+status_t SurfaceComposerClient::getHdrCapabilities(const sp<IBinder>& display,
+        HdrCapabilities* outCapabilities) {
+    return ComposerService::getComposerService()->getHdrCapabilities(display,
+            outCapabilities);
+}
+
 // ----------------------------------------------------------------------------
 
 status_t ScreenshotClient::capture(
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 1983027..314d83a 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -33,6 +33,7 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 
+#include <gui/BufferQueueCore.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
@@ -81,6 +82,13 @@
     destroy();
 }
 
+void SurfaceControl::disconnect() {
+    if (mGraphicBufferProducer != NULL) {
+        mGraphicBufferProducer->disconnect(
+                BufferQueueCore::CURRENTLY_CONNECTED_API);
+    }
+}
+
 bool SurfaceControl::isSameSurface(
         const sp<SurfaceControl>& lhs, const sp<SurfaceControl>& rhs)
 {
@@ -144,6 +152,24 @@
     if (err < 0) return err;
     return mClient->setCrop(mHandle, crop);
 }
+status_t SurfaceControl::setFinalCrop(const Rect& crop) {
+    status_t err = validate();
+    if (err < 0) return err;
+    return mClient->setFinalCrop(mHandle, crop);
+}
+
+status_t SurfaceControl::deferTransactionUntil(sp<IBinder> handle,
+        uint64_t frameNumber) {
+    status_t err = validate();
+    if (err < 0) return err;
+    return mClient->deferTransactionUntil(mHandle, handle, frameNumber);
+}
+
+status_t SurfaceControl::setOverrideScalingMode(int32_t overrideScalingMode) {
+    status_t err = validate();
+    if (err < 0) return err;
+    return mClient->setOverrideScalingMode(mHandle, overrideScalingMode);
+}
 
 status_t SurfaceControl::clearLayerFrameStats() const {
     status_t err = validate();
@@ -190,5 +216,11 @@
     return mSurfaceData;
 }
 
+sp<IBinder> SurfaceControl::getHandle() const
+{
+    Mutex::Autolock lock(mLock);
+    return mHandle;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/gui/tests/BufferQueue_test.cpp b/libs/gui/tests/BufferQueue_test.cpp
index 1a54875..85d63b4 100644
--- a/libs/gui/tests/BufferQueue_test.cpp
+++ b/libs/gui/tests/BufferQueue_test.cpp
@@ -65,6 +65,27 @@
         BufferQueue::createBufferQueue(&mProducer, &mConsumer);
     }
 
+    void testBufferItem(const IGraphicBufferProducer::QueueBufferInput& input,
+            const BufferItem& item) {
+        int64_t timestamp;
+        bool isAutoTimestamp;
+        android_dataspace dataSpace;
+        Rect crop;
+        int scalingMode;
+        uint32_t transform;
+        sp<Fence> fence;
+
+        input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
+                &scalingMode, &transform, &fence, NULL);
+        ASSERT_EQ(timestamp, item.mTimestamp);
+        ASSERT_EQ(isAutoTimestamp, item.mIsAutoTimestamp);
+        ASSERT_EQ(dataSpace, item.mDataSpace);
+        ASSERT_EQ(crop, item.mCrop);
+        ASSERT_EQ(static_cast<uint32_t>(scalingMode), item.mScalingMode);
+        ASSERT_EQ(transform, item.mTransform);
+        ASSERT_EQ(fence, item.mFence);
+    }
+
     sp<IGraphicBufferProducer> mProducer;
     sp<IGraphicBufferConsumer> mConsumer;
 };
@@ -113,7 +134,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
@@ -125,7 +146,7 @@
 
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     BufferItem item;
@@ -145,19 +166,19 @@
     IGraphicBufferProducer::QueueBufferOutput qbo;
     mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
             &qbo);
-    mProducer->setBufferCount(4);
+    mProducer->setMaxDequeuedBufferCount(3);
 
     int slot;
     sp<Fence> fence;
     sp<GraphicBuffer> buf;
     IGraphicBufferProducer::QueueBufferInput qbi(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     BufferItem item;
 
     for (int i = 0; i < 2; i++) {
         ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-                mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
+                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
                     GRALLOC_USAGE_SW_READ_OFTEN));
         ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
         ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
@@ -165,7 +186,7 @@
     }
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 1, 1, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
                 GRALLOC_USAGE_SW_READ_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
@@ -179,6 +200,14 @@
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
+    EXPECT_EQ(OK, mConsumer->setMaxBufferCount(10));
+    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(10));
+
+    IGraphicBufferProducer::QueueBufferOutput qbo;
+    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
+            &qbo);
+    mProducer->setMaxDequeuedBufferCount(3);
+
     int minBufferCount;
     ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
     EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
@@ -189,6 +218,25 @@
     EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(
             BufferQueue::MAX_MAX_ACQUIRED_BUFFERS+1));
     EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(100));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buf;
+    IGraphicBufferProducer::QueueBufferInput qbi(0, false,
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    BufferItem item;
+    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
+    for (int i = 0; i < 3; i++) {
+        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
+                    GRALLOC_USAGE_SW_READ_OFTEN));
+        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
+        ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
+        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+    }
+
+    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxAcquiredBufferCount(2));
 }
 
 TEST_F(BufferQueueTest, SetMaxAcquiredBufferCountWithLegalValues_Succeeds) {
@@ -196,16 +244,70 @@
     sp<DummyConsumer> dc(new DummyConsumer);
     mConsumer->consumerConnect(dc, false);
 
+    IGraphicBufferProducer::QueueBufferOutput qbo;
+    mProducer->connect(new DummyProducerListener, NATIVE_WINDOW_API_CPU, false,
+            &qbo);
+    mProducer->setMaxDequeuedBufferCount(2);
+
     int minBufferCount;
     ASSERT_NO_FATAL_FAILURE(GetMinUndequeuedBufferCount(&minBufferCount));
 
     EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
     EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(2));
     EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(minBufferCount));
+
+    int slot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buf;
+    IGraphicBufferProducer::QueueBufferInput qbi(0, false,
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    BufferItem item;
+
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
+            GRALLOC_USAGE_SW_READ_OFTEN));
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
+    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+
+    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(3));
+
+    for (int i = 0; i < 2; i++) {
+        ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+                mProducer->dequeueBuffer(&slot, &fence, 1, 1, 0,
+                GRALLOC_USAGE_SW_READ_OFTEN));
+        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buf));
+        ASSERT_EQ(OK, mProducer->queueBuffer(slot, qbi, &qbo));
+        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+    }
+
     EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(
             BufferQueue::MAX_MAX_ACQUIRED_BUFFERS));
 }
 
+TEST_F(BufferQueueTest, SetMaxBufferCountWithLegalValues_Succeeds) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mConsumer->consumerConnect(dc, false);
+
+    // Test shared buffer mode
+    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(1));
+}
+
+TEST_F(BufferQueueTest, SetMaxBufferCountWithIllegalValues_ReturnsError) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    mConsumer->consumerConnect(dc, false);
+
+    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(0));
+    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(
+            BufferQueue::NUM_BUFFER_SLOTS + 1));
+
+    EXPECT_EQ(OK, mConsumer->setMaxAcquiredBufferCount(5));
+    EXPECT_EQ(BAD_VALUE, mConsumer->setMaxBufferCount(3));
+}
+
 TEST_F(BufferQueueTest, DetachAndReattachOnProducerSide) {
     createBufferQueue();
     sp<DummyConsumer> dc(new DummyConsumer);
@@ -223,7 +325,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(BAD_VALUE, mProducer->detachBuffer(slot)); // Not requested
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
@@ -247,7 +349,7 @@
     ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, buffer));
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(newSlot, input, &output));
 
     BufferItem item;
@@ -272,12 +374,12 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(-1)); // Index too low
@@ -288,8 +390,8 @@
     BufferItem item;
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
 
-    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
-    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mBuf)); // Not acquired
+    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
+    ASSERT_EQ(BAD_VALUE, mConsumer->detachBuffer(item.mSlot)); // Not acquired
 
     uint32_t* dataIn;
     ASSERT_EQ(OK, item.mGraphicBuffer->lock(
@@ -308,7 +410,7 @@
             EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
@@ -331,7 +433,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
 
@@ -343,12 +445,12 @@
 
     IGraphicBufferProducer::QueueBufferInput input(0, false,
             HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
-            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false, Fence::NO_FENCE);
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
 
     BufferItem item;
     ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, static_cast<nsecs_t>(0)));
-    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mBuf));
+    ASSERT_EQ(OK, mConsumer->detachBuffer(item.mSlot));
 
     int newSlot;
     ASSERT_EQ(OK, mProducer->attachBuffer(&newSlot, item.mGraphicBuffer));
@@ -380,13 +482,13 @@
     sp<GraphicBuffer> buffer;
     // This should return an error since it would require an allocation
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
+    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, 0, 0,
             0, GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     // This should succeed, now that we've lifted the prohibition
     ASSERT_EQ(OK, mProducer->allowAllocation(true));
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
             GRALLOC_USAGE_SW_WRITE_OFTEN));
 
     // Release the previous buffer back to the BufferQueue
@@ -394,7 +496,7 @@
 
     // This should fail since we're requesting a different size
     ASSERT_EQ(OK, mProducer->allowAllocation(false));
-    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence, false,
+    ASSERT_EQ(WOULD_BLOCK, mProducer->dequeueBuffer(&slot, &fence,
             WIDTH * 2, HEIGHT * 2, 0, GRALLOC_USAGE_SW_WRITE_OFTEN));
 }
 
@@ -412,7 +514,7 @@
     int slot;
     sp<Fence> fence;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0, 0));
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
 
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
@@ -440,4 +542,312 @@
     ASSERT_EQ(OK, mConsumer->attachBuffer(&outSlot, buffer));
 }
 
+TEST_F(BufferQueueTest, TestSharedBufferModeWithoutAutoRefresh) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, true, &output));
+
+    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
+
+    // Get a buffer
+    int sharedSlot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
+
+    // Queue the buffer
+    IGraphicBufferProducer::QueueBufferInput input(0, false,
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+
+    // Repeatedly queue and dequeue a buffer from the producer side, it should
+    // always return the same one. And we won't run out of buffers because it's
+    // always the same one and because async mode gets enabled.
+    int slot;
+    for (int i = 0; i < 5; i++) {
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+        ASSERT_EQ(sharedSlot, slot);
+        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+    }
+
+    // acquire the buffer
+    BufferItem item;
+    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+    ASSERT_EQ(sharedSlot, item.mSlot);
+    testBufferItem(input, item);
+    ASSERT_EQ(true, item.mQueuedBuffer);
+    ASSERT_EQ(false, item.mAutoRefresh);
+
+    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+
+    // attempt to acquire a second time should return no buffer available
+    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
+            mConsumer->acquireBuffer(&item, 0));
+}
+
+TEST_F(BufferQueueTest, TestSharedBufferModeWithAutoRefresh) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, true, &output));
+
+    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
+    ASSERT_EQ(OK, mProducer->setAutoRefresh(true));
+
+    // Get a buffer
+    int sharedSlot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
+
+    // Queue the buffer
+    IGraphicBufferProducer::QueueBufferInput input(0, false,
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+
+    // Repeatedly acquire and release a buffer from the consumer side, it should
+    // always return the same one.
+    BufferItem item;
+    for (int i = 0; i < 5; i++) {
+        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+        ASSERT_EQ(sharedSlot, item.mSlot);
+        testBufferItem(input, item);
+        ASSERT_EQ(i == 0, item.mQueuedBuffer);
+        ASSERT_EQ(true, item.mAutoRefresh);
+
+        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+    }
+
+    // Repeatedly queue and dequeue a buffer from the producer side, it should
+    // always return the same one.
+    int slot;
+    for (int i = 0; i < 5; i++) {
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+        ASSERT_EQ(sharedSlot, slot);
+        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+    }
+
+    // Repeatedly acquire and release a buffer from the consumer side, it should
+    // always return the same one. First grabbing them from the queue and then
+    // when the queue is empty, returning the shared buffer.
+    for (int i = 0; i < 10; i++) {
+        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+        ASSERT_EQ(sharedSlot, item.mSlot);
+        ASSERT_EQ(0, item.mTimestamp);
+        ASSERT_EQ(false, item.mIsAutoTimestamp);
+        ASSERT_EQ(HAL_DATASPACE_UNKNOWN, item.mDataSpace);
+        ASSERT_EQ(Rect(0, 0, 1, 1), item.mCrop);
+        ASSERT_EQ(NATIVE_WINDOW_SCALING_MODE_FREEZE, item.mScalingMode);
+        ASSERT_EQ(0u, item.mTransform);
+        ASSERT_EQ(Fence::NO_FENCE, item.mFence);
+        ASSERT_EQ(i == 0, item.mQueuedBuffer);
+        ASSERT_EQ(true, item.mAutoRefresh);
+
+        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+                EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+    }
+}
+
+TEST_F(BufferQueueTest, TestSharedBufferModeUsingAlreadyDequeuedBuffer) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, true, &output));
+
+    // Dequeue a buffer
+    int sharedSlot;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&sharedSlot, &fence, 0, 0, 0, 0));
+    ASSERT_EQ(OK, mProducer->requestBuffer(sharedSlot, &buffer));
+
+    // Enable shared buffer mode
+    ASSERT_EQ(OK, mProducer->setSharedBufferMode(true));
+
+    // Queue the buffer
+    IGraphicBufferProducer::QueueBufferInput input(0, false,
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+
+    // Repeatedly queue and dequeue a buffer from the producer side, it should
+    // always return the same one. And we won't run out of buffers because it's
+    // always the same one and because async mode gets enabled.
+    int slot;
+    for (int i = 0; i < 5; i++) {
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+        ASSERT_EQ(sharedSlot, slot);
+        ASSERT_EQ(OK, mProducer->queueBuffer(sharedSlot, input, &output));
+    }
+
+    // acquire the buffer
+    BufferItem item;
+    ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+    ASSERT_EQ(sharedSlot, item.mSlot);
+    testBufferItem(input, item);
+    ASSERT_EQ(true, item.mQueuedBuffer);
+    ASSERT_EQ(false, item.mAutoRefresh);
+
+    ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+            EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+
+    // attempt to acquire a second time should return no buffer available
+    ASSERT_EQ(IGraphicBufferConsumer::NO_BUFFER_AVAILABLE,
+            mConsumer->acquireBuffer(&item, 0));
+}
+
+TEST_F(BufferQueueTest, TestTimeouts) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, true, &output));
+
+    // Fill up the queue. Since the controlledByApp flags are set to true, this
+    // queue should be in non-blocking mode, and we should be recycling the same
+    // two buffers
+    for (int i = 0; i < 5; ++i) {
+        int slot = BufferQueue::INVALID_BUFFER_SLOT;
+        sp<Fence> fence = Fence::NO_FENCE;
+        auto result = mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0);
+        if (i < 2) {
+            ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+                    result);
+        } else {
+            ASSERT_EQ(OK, result);
+        }
+        sp<GraphicBuffer> buffer;
+        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+        IGraphicBufferProducer::QueueBufferInput input(0ull, true,
+                HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
+                NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+        IGraphicBufferProducer::QueueBufferOutput output{};
+        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+    }
+
+    const auto TIMEOUT = ms2ns(250);
+    mProducer->setDequeueTimeout(TIMEOUT);
+
+    // Setting a timeout will change the BufferQueue into blocking mode (with
+    // one droppable buffer in the queue and one free from the previous
+    // dequeue/queues), so dequeue and queue two more buffers: one to replace
+    // the current droppable buffer, and a second to max out the buffer count
+    sp<GraphicBuffer> buffer; // Save a buffer to attach later
+    for (int i = 0; i < 2; ++i) {
+        int slot = BufferQueue::INVALID_BUFFER_SLOT;
+        sp<Fence> fence = Fence::NO_FENCE;
+        ASSERT_EQ(OK, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+        ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+        IGraphicBufferProducer::QueueBufferInput input(0ull, true,
+                HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
+                NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+        ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+    }
+
+    int slot = BufferQueue::INVALID_BUFFER_SLOT;
+    sp<Fence> fence = Fence::NO_FENCE;
+    auto startTime = systemTime();
+    ASSERT_EQ(TIMED_OUT, mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+    ASSERT_GE(systemTime() - startTime, TIMEOUT);
+
+    // We're technically attaching the same buffer multiple times (since we
+    // queued it previously), but that doesn't matter for this test
+    startTime = systemTime();
+    ASSERT_EQ(TIMED_OUT, mProducer->attachBuffer(&slot, buffer));
+    ASSERT_GE(systemTime() - startTime, TIMEOUT);
+}
+
+TEST_F(BufferQueueTest, CanAttachWhileDisallowingAllocation) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, true));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, true, &output));
+
+    int slot = BufferQueue::INVALID_BUFFER_SLOT;
+    sp<Fence> sourceFence;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &sourceFence, 0, 0, 0, 0));
+    sp<GraphicBuffer> buffer;
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &buffer));
+    ASSERT_EQ(OK, mProducer->detachBuffer(slot));
+
+    ASSERT_EQ(OK, mProducer->allowAllocation(false));
+
+    slot = BufferQueue::INVALID_BUFFER_SLOT;
+    ASSERT_EQ(OK, mProducer->attachBuffer(&slot, buffer));
+}
+
+TEST_F(BufferQueueTest, CanRetrieveLastQueuedBuffer) {
+    createBufferQueue();
+    sp<DummyConsumer> dc(new DummyConsumer);
+    ASSERT_EQ(OK, mConsumer->consumerConnect(dc, false));
+    IGraphicBufferProducer::QueueBufferOutput output;
+    ASSERT_EQ(OK, mProducer->connect(new DummyProducerListener,
+            NATIVE_WINDOW_API_CPU, false, &output));
+
+    // Dequeue and queue the first buffer, storing the handle
+    int slot = BufferQueue::INVALID_BUFFER_SLOT;
+    sp<Fence> fence;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+    sp<GraphicBuffer> firstBuffer;
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &firstBuffer));
+
+    IGraphicBufferProducer::QueueBufferInput input(0ull, true,
+        HAL_DATASPACE_UNKNOWN, Rect::INVALID_RECT,
+        NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    // Dequeue a second buffer
+    slot = BufferQueue::INVALID_BUFFER_SLOT;
+    ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
+            mProducer->dequeueBuffer(&slot, &fence, 0, 0, 0, 0));
+    sp<GraphicBuffer> secondBuffer;
+    ASSERT_EQ(OK, mProducer->requestBuffer(slot, &secondBuffer));
+
+    // Ensure it's a new buffer
+    ASSERT_NE(firstBuffer->getNativeBuffer()->handle,
+            secondBuffer->getNativeBuffer()->handle);
+
+    // Queue the second buffer
+    ASSERT_EQ(OK, mProducer->queueBuffer(slot, input, &output));
+
+    // Acquire and release both buffers
+    for (size_t i = 0; i < 2; ++i) {
+        BufferItem item;
+        ASSERT_EQ(OK, mConsumer->acquireBuffer(&item, 0));
+        ASSERT_EQ(OK, mConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
+                    EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
+    }
+
+    // Make sure we got the second buffer back
+    sp<GraphicBuffer> returnedBuffer;
+    sp<Fence> returnedFence;
+    float transform[16];
+    ASSERT_EQ(OK,
+            mProducer->getLastQueuedBuffer(&returnedBuffer, &returnedFence,
+            transform));
+    ASSERT_EQ(secondBuffer->getNativeBuffer()->handle,
+            returnedBuffer->getNativeBuffer()->handle);
+}
+
 } // namespace android
diff --git a/libs/gui/tests/CpuConsumer_test.cpp b/libs/gui/tests/CpuConsumer_test.cpp
index 2dc9ccc..289cc74 100644
--- a/libs/gui/tests/CpuConsumer_test.cpp
+++ b/libs/gui/tests/CpuConsumer_test.cpp
@@ -444,19 +444,14 @@
     }
 }
 
-void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride,
-        const android_native_rect_t& rect);
-
-void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride);
-
-void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r,
-        uint8_t g, uint8_t b, uint8_t a);
-
 // Configures the ANativeWindow producer-side interface based on test parameters
 void configureANW(const sp<ANativeWindow>& anw,
         const CpuConsumerTestParams& params,
         int maxBufferSlack) {
     status_t err;
+    err = native_window_api_connect(anw.get(), NATIVE_WINDOW_API_CPU);
+    ASSERT_NO_ERROR(err, "connect error: ");
+
     err = native_window_set_buffers_dimensions(anw.get(),
             params.width, params.height);
     ASSERT_NO_ERROR(err, "set_buffers_dimensions error: ");
diff --git a/libs/gui/tests/GLTest.h b/libs/gui/tests/GLTest.h
index d3c4a95..f0d27a8 100644
--- a/libs/gui/tests/GLTest.h
+++ b/libs/gui/tests/GLTest.h
@@ -35,9 +35,11 @@
 
 protected:
     GLTest() :
+            mDisplaySecs(0),
             mEglDisplay(EGL_NO_DISPLAY),
             mEglSurface(EGL_NO_SURFACE),
-            mEglContext(EGL_NO_CONTEXT) {
+            mEglContext(EGL_NO_CONTEXT),
+            mGlConfig(NULL) {
     }
 
     virtual void SetUp();
diff --git a/libs/gui/tests/IGraphicBufferProducer_test.cpp b/libs/gui/tests/IGraphicBufferProducer_test.cpp
index 4ef9a69..45b6463 100644
--- a/libs/gui/tests/IGraphicBufferProducer_test.cpp
+++ b/libs/gui/tests/IGraphicBufferProducer_test.cpp
@@ -61,7 +61,6 @@
     const Rect QUEUE_BUFFER_INPUT_RECT = Rect(DEFAULT_WIDTH, DEFAULT_HEIGHT);
     const int QUEUE_BUFFER_INPUT_SCALING_MODE = 0;
     const int QUEUE_BUFFER_INPUT_TRANSFORM = 0;
-    const bool QUEUE_BUFFER_INPUT_ASYNC = false;
     const sp<Fence> QUEUE_BUFFER_INPUT_FENCE = Fence::NO_FENCE;
 }; // namespace anonymous
 
@@ -131,7 +130,6 @@
            crop = QUEUE_BUFFER_INPUT_RECT;
            scalingMode = QUEUE_BUFFER_INPUT_SCALING_MODE;
            transform = QUEUE_BUFFER_INPUT_TRANSFORM;
-           async = QUEUE_BUFFER_INPUT_ASYNC;
            fence = QUEUE_BUFFER_INPUT_FENCE;
         }
 
@@ -143,7 +141,6 @@
                     crop,
                     scalingMode,
                     transform,
-                    async,
                     fence);
         }
 
@@ -177,11 +174,6 @@
             return *this;
         }
 
-        QueueBufferInputBuilder& setAsync(bool async) {
-            this->async = async;
-            return *this;
-        }
-
         QueueBufferInputBuilder& setFence(sp<Fence> fence) {
             this->fence = fence;
             return *this;
@@ -194,7 +186,6 @@
         Rect crop;
         int scalingMode;
         uint32_t transform;
-        int async;
         sp<Fence> fence;
     }; // struct QueueBufferInputBuilder
 
@@ -204,8 +195,28 @@
         sp<Fence> fence;
     };
 
-    status_t dequeueBuffer(bool async, uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
-        return mProducer->dequeueBuffer(&result->slot, &result->fence, async, w, h, format, usage);
+    status_t dequeueBuffer(uint32_t w, uint32_t h, uint32_t format, uint32_t usage, DequeueBufferResult* result) {
+        return mProducer->dequeueBuffer(&result->slot, &result->fence, w, h, format, usage);
+    }
+
+    void setupDequeueRequestBuffer(int *slot, sp<Fence> *fence,
+            sp<GraphicBuffer> *buffer)
+    {
+        ASSERT_TRUE(slot != NULL);
+        ASSERT_TRUE(fence != NULL);
+        ASSERT_TRUE(buffer != NULL);
+
+        ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(slot, fence, DEFAULT_WIDTH,
+                DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+
+        EXPECT_LE(0, *slot);
+        EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, *slot);
+
+        // Request the buffer (pre-requisite for queueing)
+        ASSERT_OK(mProducer->requestBuffer(*slot, buffer));
     }
 
 private: // hide from test body
@@ -334,12 +345,11 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    // XX: OK to assume first call returns this flag or not? Not really documented.
-    ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     QUEUE_BUFFER_INPUT_ASYNC,
+
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS));
+                                     TEST_PRODUCER_USAGE_BITS)));
 
     EXPECT_LE(0, dequeuedSlot);
     EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
@@ -400,11 +410,10 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     QUEUE_BUFFER_INPUT_ASYNC,
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS));
+                                     TEST_PRODUCER_USAGE_BITS)));
 
     // Slot was enqueued without requesting a buffer
     {
@@ -470,103 +479,252 @@
     int dequeuedSlot = -1;
     sp<Fence> dequeuedFence;
 
-    ASSERT_EQ(OK | IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                     QUEUE_BUFFER_INPUT_ASYNC,
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
                                      DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                     TEST_PRODUCER_USAGE_BITS));
+                                     TEST_PRODUCER_USAGE_BITS)));
 
     // No return code, but at least test that it doesn't blow up...
     // TODO: add a return code
     mProducer->cancelBuffer(dequeuedSlot, dequeuedFence);
 }
 
-TEST_F(IGraphicBufferProducerTest, SetBufferCount_Succeeds) {
+TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Succeeds) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+    int minUndequeuedBuffers;
+    ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+            &minUndequeuedBuffers));
 
-    // The producer does not wish to set a buffer count
-    EXPECT_OK(mProducer->setBufferCount(0)) << "bufferCount: " << 0;
-    // TODO: how to test "0" buffer count?
+    const int minBuffers = 1;
+    const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
 
-    int minBuffers;
-    ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minBuffers));
-
-    // The MIN_UNDEQUEUED_BUFFERS limit is exclusive, so need to increment by at least 1
-    minBuffers++;
-
-    ASSERT_OK(mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
-
-    std::vector<DequeueBufferResult> dequeueList;
+    ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
+    ASSERT_OK(mProducer->setMaxDequeuedBufferCount(minBuffers))
+            << "bufferCount: " << minBuffers;
 
     // Should now be able to dequeue up to minBuffers times
+    DequeueBufferResult result;
     for (int i = 0; i < minBuffers; ++i) {
-        DequeueBufferResult result;
 
-        EXPECT_LE(OK,
-                dequeueBuffer(QUEUE_BUFFER_INPUT_ASYNC,
-                              DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                              TEST_PRODUCER_USAGE_BITS, &result))
+        EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (dequeueBuffer(DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                              TEST_PRODUCER_USAGE_BITS, &result)))
                 << "iteration: " << i << ", slot: " << result.slot;
-
-        dequeueList.push_back(result);
     }
 
-    // Cancel every buffer, so we can set buffer count again
-    for (int i = 0; i < minBuffers; ++i) {
-        DequeueBufferResult& result = dequeueList[i];
-        mProducer->cancelBuffer(result.slot, result.fence);
-    }
+    ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers));
 
-    ASSERT_OK(mProducer->setBufferCount(BufferQueue::NUM_BUFFER_SLOTS));
+    // queue the first buffer to enable max dequeued buffer count checking
+    IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+    IGraphicBufferProducer::QueueBufferOutput output;
+    sp<GraphicBuffer> buffer;
+    ASSERT_OK(mProducer->requestBuffer(result.slot, &buffer));
+    ASSERT_OK(mProducer->queueBuffer(result.slot, input, &output));
 
-    // Should now be able to dequeue up to NUM_BUFFER_SLOTS times
-    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; ++i) {
-        int dequeuedSlot = -1;
-        sp<Fence> dequeuedFence;
 
-        EXPECT_LE(OK,
-                mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         QUEUE_BUFFER_INPUT_ASYNC,
-                                         DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS))
+    // Should now be able to dequeue up to maxBuffers times
+    int dequeuedSlot = -1;
+    sp<Fence> dequeuedFence;
+    for (int i = 0; i < maxBuffers; ++i) {
+
+        EXPECT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+                                         DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                         DEFAULT_FORMAT,
+                                         TEST_PRODUCER_USAGE_BITS)))
                 << "iteration: " << i << ", slot: " << dequeuedSlot;
     }
+
+    // Cancel a buffer, so we can decrease the buffer count
+    ASSERT_OK(mProducer->cancelBuffer(dequeuedSlot, dequeuedFence));
+
+    // Should now be able to decrease the max dequeued count by 1
+    ASSERT_OK(mProducer->setMaxDequeuedBufferCount(maxBuffers-1));
 }
 
-TEST_F(IGraphicBufferProducerTest, SetBufferCount_Fails) {
-    int minBuffers;
-    ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minBuffers));
+TEST_F(IGraphicBufferProducerTest, SetMaxDequeuedBufferCount_Fails) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+    int minUndequeuedBuffers;
+    ASSERT_OK(mProducer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                               &minUndequeuedBuffers));
 
-    // The MIN_UNDEQUEUED_BUFFERS limit is exclusive, so need to increment by at least 1
-    minBuffers++;
+    const int minBuffers = 1;
+    const int maxBuffers = BufferQueue::NUM_BUFFER_SLOTS - minUndequeuedBuffers;
 
+    ASSERT_OK(mProducer->setAsyncMode(false)) << "async mode: " << false;
     // Buffer count was out of range
-    EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(-1)) << "bufferCount: " << -1;
-    EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(minBuffers - 1)) << "bufferCount: " << minBuffers - 1;
-    EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(BufferQueue::NUM_BUFFER_SLOTS + 1))
-            << "bufferCount: " << BufferQueue::NUM_BUFFER_SLOTS + 1;
+    EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(0))
+            << "bufferCount: " << 0;
+    EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(maxBuffers + 1))
+            << "bufferCount: " << maxBuffers + 1;
 
-    // Pre-requisite to fail out a valid setBufferCount call
-    {
-        int dequeuedSlot = -1;
-        sp<Fence> dequeuedFence;
-
-        ASSERT_LE(OK,
-                mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
-                                         QUEUE_BUFFER_INPUT_ASYNC,
-                                         DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
-                                         TEST_PRODUCER_USAGE_BITS))
+    // Set max dequeue count to 2
+    ASSERT_OK(mProducer->setMaxDequeuedBufferCount(2));
+    // Dequeue 2 buffers
+    int dequeuedSlot = -1;
+    sp<Fence> dequeuedFence;
+    for (int i = 0; i < 2; i++) {
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+                                         DEFAULT_WIDTH, DEFAULT_HEIGHT,
+                                         DEFAULT_FORMAT,
+                                         TEST_PRODUCER_USAGE_BITS)))
                 << "slot: " << dequeuedSlot;
     }
 
-    // Client has one or more buffers dequeued
-    EXPECT_EQ(BAD_VALUE, mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
+    // Client has too many buffers dequeued
+    EXPECT_EQ(BAD_VALUE, mProducer->setMaxDequeuedBufferCount(1))
+            << "bufferCount: " << minBuffers;
 
     // Abandon buffer queue
     ASSERT_OK(mConsumer->consumerDisconnect());
 
     // Fail because the buffer queue was abandoned
-    EXPECT_EQ(NO_INIT, mProducer->setBufferCount(minBuffers)) << "bufferCount: " << minBuffers;
+    EXPECT_EQ(NO_INIT, mProducer->setMaxDequeuedBufferCount(minBuffers))
+            << "bufferCount: " << minBuffers;
 
 }
 
+TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Succeeds) {
+    ASSERT_OK(mConsumer->setMaxAcquiredBufferCount(1)) << "maxAcquire: " << 1;
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+    ASSERT_OK(mProducer->setAsyncMode(true)) << "async mode: " << true;
+    ASSERT_OK(mProducer->setMaxDequeuedBufferCount(1)) << "maxDequeue: " << 1;
+
+    int dequeuedSlot = -1;
+    sp<Fence> dequeuedFence;
+    IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+    IGraphicBufferProducer::QueueBufferOutput output;
+    sp<GraphicBuffer> dequeuedBuffer;
+
+    // Should now be able to queue/dequeue as many buffers as we want without
+    // blocking
+    for (int i = 0; i < 5; ++i) {
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                TEST_PRODUCER_USAGE_BITS))) << "slot : " << dequeuedSlot;
+        ASSERT_OK(mProducer->requestBuffer(dequeuedSlot, &dequeuedBuffer));
+        ASSERT_OK(mProducer->queueBuffer(dequeuedSlot, input, &output));
+    }
+}
+
+TEST_F(IGraphicBufferProducerTest, SetAsyncMode_Fails) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+    // Prerequisite to fail out a valid setBufferCount call
+    {
+        int dequeuedSlot = -1;
+        sp<Fence> dequeuedFence;
+
+        ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+                (mProducer->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
+                DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_FORMAT,
+                TEST_PRODUCER_USAGE_BITS))) << "slot: " << dequeuedSlot;
+    }
+
+    // Abandon buffer queue
+    ASSERT_OK(mConsumer->consumerDisconnect());
+
+    // Fail because the buffer queue was abandoned
+    EXPECT_EQ(NO_INIT, mProducer->setAsyncMode(false)) << "asyncMode: "
+            << false;
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_dequeueBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+
+    ASSERT_EQ(NO_INIT, mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
+            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_detachNextBuffer) {
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    ASSERT_EQ(NO_INIT, mProducer->detachNextBuffer(&buffer, &fence));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_requestBuffer) {
+    ASSERT_NO_FATAL_FAILURE(ConnectProducer());
+
+    int slot = -1;
+    sp<Fence> fence;
+
+    ASSERT_EQ(OK, ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
+            (mProducer->dequeueBuffer(&slot, &fence, DEFAULT_WIDTH,
+            DEFAULT_HEIGHT, DEFAULT_FORMAT, TEST_PRODUCER_USAGE_BITS)));
+
+    EXPECT_LE(0, slot);
+    EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, slot);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    sp<GraphicBuffer> buffer;
+
+    ASSERT_EQ(NO_INIT, mProducer->requestBuffer(slot, &buffer));
+}
+
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_detachBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    ASSERT_EQ(NO_INIT, mProducer->detachBuffer(slot));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_queueBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    // A generic "valid" input
+    IGraphicBufferProducer::QueueBufferInput input = CreateBufferInput();
+    IGraphicBufferProducer::QueueBufferOutput output;
+
+    ASSERT_EQ(NO_INIT, mProducer->queueBuffer(slot, input, &output));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_cancelBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    ASSERT_EQ(NO_INIT, mProducer->cancelBuffer(slot, fence));
+}
+
+TEST_F(IGraphicBufferProducerTest,
+        DisconnectedProducerReturnsError_attachBuffer) {
+    int slot = -1;
+    sp<Fence> fence;
+    sp<GraphicBuffer> buffer;
+
+    setupDequeueRequestBuffer(&slot, &fence, &buffer);
+
+    ASSERT_OK(mProducer->detachBuffer(slot));
+
+    ASSERT_OK(mProducer->disconnect(TEST_API));
+
+    ASSERT_EQ(NO_INIT, mProducer->attachBuffer(&slot, buffer));
+}
+
 } // namespace android
diff --git a/libs/gui/tests/StreamSplitter_test.cpp b/libs/gui/tests/StreamSplitter_test.cpp
index 00cc39d..498492e 100644
--- a/libs/gui/tests/StreamSplitter_test.cpp
+++ b/libs/gui/tests/StreamSplitter_test.cpp
@@ -52,42 +52,16 @@
     virtual void onSidebandStreamChanged() {}
 };
 
-class CountedAllocator : public BnGraphicBufferAlloc {
-public:
-    CountedAllocator() : mAllocCount(0) {
-        sp<ISurfaceComposer> composer(ComposerService::getComposerService());
-        mAllocator = composer->createGraphicBufferAlloc();
-    }
-
-    virtual ~CountedAllocator() {}
-
-    virtual sp<GraphicBuffer> createGraphicBuffer(uint32_t w, uint32_t h,
-            PixelFormat format, uint32_t usage, status_t* error) {
-        ++mAllocCount;
-        sp<GraphicBuffer> buffer = mAllocator->createGraphicBuffer(w, h, format,
-                usage, error);
-        return buffer;
-    }
-
-    int getAllocCount() const { return mAllocCount; }
-
-private:
-    sp<IGraphicBufferAlloc> mAllocator;
-    int mAllocCount;
-};
-
 static const uint32_t TEST_DATA = 0x12345678u;
 
 TEST_F(StreamSplitterTest, OneInputOneOutput) {
-    sp<CountedAllocator> allocator(new CountedAllocator);
-
     sp<IGraphicBufferProducer> inputProducer;
     sp<IGraphicBufferConsumer> inputConsumer;
-    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer, allocator);
+    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);
 
     sp<IGraphicBufferProducer> outputProducer;
     sp<IGraphicBufferConsumer> outputConsumer;
-    BufferQueue::createBufferQueue(&outputProducer, &outputConsumer, allocator);
+    BufferQueue::createBufferQueue(&outputProducer, &outputConsumer);
     ASSERT_EQ(OK, outputConsumer->consumerConnect(new DummyListener, false));
 
     sp<StreamSplitter> splitter;
@@ -95,6 +69,9 @@
     ASSERT_EQ(OK, status);
     ASSERT_EQ(OK, splitter->addOutput(outputProducer));
 
+    // Never allow the output BufferQueue to allocate a buffer
+    ASSERT_EQ(OK, outputProducer->allowAllocation(false));
+
     IGraphicBufferProducer::QueueBufferOutput qbOutput;
     ASSERT_EQ(OK, inputProducer->connect(new DummyProducerListener,
             NATIVE_WINDOW_API_CPU, false, &qbOutput));
@@ -103,7 +80,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
@@ -114,11 +91,14 @@
     ASSERT_EQ(OK, buffer->unlock());
 
     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
-            HAL_DATASPACE_UNKNOWN,
-            Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
-            Fence::NO_FENCE);
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
+    // Now that we have dequeued/allocated one buffer, prevent any further
+    // allocations
+    ASSERT_EQ(OK, inputProducer->allowAllocation(false));
+
     BufferItem item;
     ASSERT_EQ(OK, outputConsumer->acquireBuffer(&item, 0));
 
@@ -128,29 +108,28 @@
     ASSERT_EQ(*dataOut, TEST_DATA);
     ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 
-    ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mBuf, item.mFrameNumber,
+    ASSERT_EQ(OK, outputConsumer->releaseBuffer(item.mSlot, item.mFrameNumber,
             EGL_NO_DISPLAY, EGL_NO_SYNC_KHR, Fence::NO_FENCE));
 
+    // This should succeed even with allocation disabled since it will have
+    // received the buffer back from the output BufferQueue
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
-
-    ASSERT_EQ(1, allocator->getAllocCount());
 }
 
 TEST_F(StreamSplitterTest, OneInputMultipleOutputs) {
     const int NUM_OUTPUTS = 4;
-    sp<CountedAllocator> allocator(new CountedAllocator);
 
     sp<IGraphicBufferProducer> inputProducer;
     sp<IGraphicBufferConsumer> inputConsumer;
-    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer, allocator);
+    BufferQueue::createBufferQueue(&inputProducer, &inputConsumer);
 
     sp<IGraphicBufferProducer> outputProducers[NUM_OUTPUTS] = {};
     sp<IGraphicBufferConsumer> outputConsumers[NUM_OUTPUTS] = {};
     for (int output = 0; output < NUM_OUTPUTS; ++output) {
         BufferQueue::createBufferQueue(&outputProducers[output],
-                &outputConsumers[output], allocator);
+                &outputConsumers[output]);
         ASSERT_EQ(OK, outputConsumers[output]->consumerConnect(
                     new DummyListener, false));
     }
@@ -160,6 +139,9 @@
     ASSERT_EQ(OK, status);
     for (int output = 0; output < NUM_OUTPUTS; ++output) {
         ASSERT_EQ(OK, splitter->addOutput(outputProducers[output]));
+
+        // Never allow the output BufferQueues to allocate a buffer
+        ASSERT_EQ(OK, outputProducers[output]->allowAllocation(false));
     }
 
     IGraphicBufferProducer::QueueBufferOutput qbOutput;
@@ -170,7 +152,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
@@ -181,11 +163,14 @@
     ASSERT_EQ(OK, buffer->unlock());
 
     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
-            HAL_DATASPACE_UNKNOWN,
-            Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
-            Fence::NO_FENCE);
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
+    // Now that we have dequeued/allocated one buffer, prevent any further
+    // allocations
+    ASSERT_EQ(OK, inputProducer->allowAllocation(false));
+
     for (int output = 0; output < NUM_OUTPUTS; ++output) {
         BufferItem item;
         ASSERT_EQ(OK, outputConsumers[output]->acquireBuffer(&item, 0));
@@ -196,16 +181,16 @@
         ASSERT_EQ(*dataOut, TEST_DATA);
         ASSERT_EQ(OK, item.mGraphicBuffer->unlock());
 
-        ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mBuf,
+        ASSERT_EQ(OK, outputConsumers[output]->releaseBuffer(item.mSlot,
                     item.mFrameNumber, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
                     Fence::NO_FENCE));
     }
 
+    // This should succeed even with allocation disabled since it will have
+    // received the buffer back from the output BufferQueues
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
-
-    ASSERT_EQ(1, allocator->getAllocCount());
 }
 
 TEST_F(StreamSplitterTest, OutputAbandonment) {
@@ -231,7 +216,7 @@
     sp<Fence> fence;
     sp<GraphicBuffer> buffer;
     ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION,
-            inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0, 0,
+            inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
                     GRALLOC_USAGE_SW_WRITE_OFTEN));
     ASSERT_EQ(OK, inputProducer->requestBuffer(slot, &buffer));
 
@@ -239,14 +224,13 @@
     outputConsumer->consumerDisconnect();
 
     IGraphicBufferProducer::QueueBufferInput qbInput(0, false,
-            HAL_DATASPACE_UNKNOWN,
-            Rect(0, 0, 1, 1), NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, false,
-            Fence::NO_FENCE);
+            HAL_DATASPACE_UNKNOWN, Rect(0, 0, 1, 1),
+            NATIVE_WINDOW_SCALING_MODE_FREEZE, 0, Fence::NO_FENCE);
     ASSERT_EQ(OK, inputProducer->queueBuffer(slot, qbInput, &qbOutput));
 
     // Input should be abandoned
-    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, false, 0, 0,
-            0, GRALLOC_USAGE_SW_WRITE_OFTEN));
+    ASSERT_EQ(NO_INIT, inputProducer->dequeueBuffer(&slot, &fence, 0, 0, 0,
+            GRALLOC_USAGE_SW_WRITE_OFTEN));
 }
 
 } // namespace android
diff --git a/libs/gui/tests/SurfaceTextureClient_test.cpp b/libs/gui/tests/SurfaceTextureClient_test.cpp
index 1a50b24..a1578f6 100644
--- a/libs/gui/tests/SurfaceTextureClient_test.cpp
+++ b/libs/gui/tests/SurfaceTextureClient_test.cpp
@@ -37,7 +37,8 @@
     SurfaceTextureClientTest():
             mEglDisplay(EGL_NO_DISPLAY),
             mEglSurface(EGL_NO_SURFACE),
-            mEglContext(EGL_NO_CONTEXT) {
+            mEglContext(EGL_NO_CONTEXT),
+            mEglConfig(NULL) {
     }
 
     virtual void SetUp() {
@@ -215,6 +216,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, DefaultGeometryValues) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf));
     EXPECT_EQ(1, buf->width);
@@ -224,6 +226,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometryCanBeSet) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -235,6 +238,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometryDefaultSizeSetFormat) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -246,6 +250,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySetSizeDefaultFormat) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
@@ -257,6 +262,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeUnset) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 16, 8));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
@@ -275,6 +281,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, BufferGeometrySizeCanBeChangedWithoutFormat) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 0, 0));
     EXPECT_EQ(OK, native_window_set_buffers_format(mANW.get(), PIXEL_FORMAT_RGB_565));
@@ -292,6 +299,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSize) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     sp<GLConsumer> st(mST);
     ANativeWindowBuffer* buf;
     EXPECT_EQ(OK, st->setDefaultBufferSize(16, 8));
@@ -304,6 +312,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeAfterDequeue) {
     ANativeWindowBuffer* buf[2];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -324,6 +333,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSetDefaultSizeVsGeometry) {
     ANativeWindowBuffer* buf[2];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     EXPECT_EQ(OK, mST->setDefaultBufferSize(16, 8));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -350,6 +360,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureTooManyUpdateTexImage) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, mANW->setSwapInterval(mANW.get(), 0));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
 
@@ -373,6 +384,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeSlowRetire) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -393,6 +405,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeFastRetire) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
@@ -413,8 +426,8 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeDQQR) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
-
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
     EXPECT_EQ(OK, mST->updateTexImage());
@@ -438,6 +451,7 @@
 TEST_F(SurfaceTextureClientTest, DISABLED_SurfaceTextureSyncModeDequeueCurrent) {
     android_native_buffer_t* buf[3];
     android_native_buffer_t* firstBuf;
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &firstBuf));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), firstBuf, -1));
@@ -457,6 +471,7 @@
 
 TEST_F(SurfaceTextureClientTest, SurfaceTextureSyncModeMinUndequeued) {
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
 
     // We should be able to dequeue all the buffers before we've queued mANWy.
@@ -482,6 +497,7 @@
 }
 
 TEST_F(SurfaceTextureClientTest, SetCropCropsCrop) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     android_native_rect_t rect = {-2, -13, 40, 18};
     native_window_set_crop(mANW.get(), &rect);
 
@@ -536,6 +552,7 @@
     };
 
     android_native_buffer_t* buf[3];
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 3));
     // dequeue/queue/update so we have a current buffer
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
@@ -547,7 +564,7 @@
 
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
-    thread->run();
+    thread->run("MyThread");
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[1]));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[1], -1));
     //ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[2]));
@@ -559,6 +576,7 @@
 TEST_F(SurfaceTextureClientTest, GetTransformMatrixReturnsVerticalFlip) {
     android_native_buffer_t* buf[3];
     float mtx[16] = {};
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -589,6 +607,7 @@
 TEST_F(SurfaceTextureClientTest, GetTransformMatrixSucceedsAfterFreeingBuffers) {
     android_native_buffer_t* buf[3];
     float mtx[16] = {};
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &buf[0]));
     ASSERT_EQ(OK, mANW->queueBuffer(mANW.get(), buf[0], -1));
@@ -638,6 +657,7 @@
     crop.right = 5;
     crop.bottom = 5;
 
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_set_buffer_count(mANW.get(), 4));
     ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 8, 8));
     ASSERT_EQ(OK, native_window_set_buffers_format(mANW.get(), 0));
diff --git a/libs/gui/tests/SurfaceTextureFBO_test.cpp b/libs/gui/tests/SurfaceTextureFBO_test.cpp
index c243fc0..0606839 100644
--- a/libs/gui/tests/SurfaceTextureFBO_test.cpp
+++ b/libs/gui/tests/SurfaceTextureFBO_test.cpp
@@ -27,6 +27,8 @@
     const int texWidth = 64;
     const int texHeight = 64;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL.h b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
index 14e42ac..2ce20eb 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL.h
@@ -171,7 +171,7 @@
         mProducerThread = producerThread;
         producerThread->setEglObjects(mEglDisplay, mProducerEglSurface,
                 mProducerEglContext);
-        producerThread->run();
+        producerThread->run("ProducerThread");
     }
 
     sp<ProducerThread> mProducerThread;
diff --git a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
index 9776733..c4d0aaa 100644
--- a/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLThreadToGL_test.cpp
@@ -31,6 +31,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     mFC->waitForFrame();
@@ -50,6 +52,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     mFC->waitForFrame();
@@ -75,6 +79,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     for (int i = 0; i < NUM_ITERATIONS; i++) {
@@ -104,6 +110,8 @@
         }
     };
 
+    SetUpWindowAndContext();
+
     runProducerThread(new PT());
 
     for (int i = 0; i < NUM_ITERATIONS; i++) {
@@ -134,7 +142,7 @@
         }
     };
 
-    ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
+    SetUpWindowAndContext();
 
     runProducerThread(new PT());
 
diff --git a/libs/gui/tests/SurfaceTextureGLToGL.h b/libs/gui/tests/SurfaceTextureGLToGL.h
index 5a2eff3..5d43a48 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL.h
+++ b/libs/gui/tests/SurfaceTextureGLToGL.h
@@ -34,7 +34,9 @@
 
     virtual void SetUp() {
         SurfaceTextureGLTest::SetUp();
+    }
 
+    void SetUpWindowAndContext() {
         mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
                 mANW.get(), NULL);
         ASSERT_EQ(EGL_SUCCESS, eglGetError());
diff --git a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
index 6edbfb8..c28b4d1 100644
--- a/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGLToGL_test.cpp
@@ -29,8 +29,11 @@
     mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
 
     // This test requires 3 buffers to avoid deadlock because we're
-    // both producer and consumer, and only using one thread.
-    mST->setDefaultMaxBufferCount(3);
+    // both producer and consumer, and only using one thread. Set max dequeued
+    // to 2, and max acquired already defaults to 1.
+    ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
+
+    SetUpWindowAndContext();
 
     // Do the producer side of things
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -81,7 +84,10 @@
     mST->setDefaultBufferSize(texWidth, texHeight);
 
     // This test requires 3 buffers to complete run on a single thread.
-    mST->setDefaultMaxBufferCount(3);
+    // Set max dequeued to 2, and max acquired already defaults to 1.
+    ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
+
+    SetUpWindowAndContext();
 
     // Do the producer side of things
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -150,6 +156,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffers[2];
 
     // This test requires async mode to run on a single thread.
@@ -195,6 +202,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffers[3];
 
     // This test requires async mode to run on a single thread.
@@ -252,6 +260,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentBeforeConsumerDeathUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffer;
 
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -289,6 +298,7 @@
 }
 
 TEST_F(SurfaceTextureGLToGLTest, EglMakeCurrentAfterConsumerDeathUnrefsBuffers) {
+    SetUpWindowAndContext();
     sp<GraphicBuffer> buffer;
 
     EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
@@ -330,7 +340,10 @@
     enum { texHeight = 64 };
 
     // This test requires 3 buffers to complete run on a single thread.
-    mST->setDefaultMaxBufferCount(3);
+    // Set max dequeued to 2, and max acquired already defaults to 1.
+    ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
+
+    SetUpWindowAndContext();
 
     // Set the user buffer size.
     native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
@@ -387,7 +400,10 @@
     enum { texHeight = 16 };
 
     // This test requires 3 buffers to complete run on a single thread.
-    mST->setDefaultMaxBufferCount(3);
+    // Set max dequeued to 2, and max acquired already defaults to 1.
+    ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
+
+    SetUpWindowAndContext();
 
     // Set the transform hint.
     mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
@@ -448,7 +464,10 @@
     enum { texHeight = 16 };
 
     // This test requires 3 buffers to complete run on a single thread.
-    mST->setDefaultMaxBufferCount(3);
+    // Set max dequeued to 2, and max acquired already defaults to 1.
+    ASSERT_EQ(OK, mSTC->setMaxDequeuedBufferCount(2));
+
+    SetUpWindowAndContext();
 
     // Set the transform hint.
     mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
diff --git a/libs/gui/tests/SurfaceTextureGL_test.cpp b/libs/gui/tests/SurfaceTextureGL_test.cpp
index fad133f..dddcf92 100644
--- a/libs/gui/tests/SurfaceTextureGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureGL_test.cpp
@@ -28,6 +28,8 @@
     const int texWidth = 64;
     const int texHeight = 66;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -76,6 +78,8 @@
     const int texWidth = 64;
     const int texHeight = 64;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -124,6 +128,8 @@
     const int texWidth = 64;
     const int texHeight = 66;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -190,7 +196,8 @@
     enum { texHeight = 16 };
     enum { numFrames = 1024 };
 
-    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -288,7 +295,7 @@
     };
 
     sp<Thread> pt(new ProducerThread(mANW, testPixels));
-    pt->run();
+    pt->run("ProducerThread");
 
     glViewport(0, 0, texWidth, texHeight);
 
@@ -334,6 +341,8 @@
     const int texWidth = 64;
     const int texHeight = 66;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -378,6 +387,8 @@
     const int texWidth = 64;
     const int texHeight = 64;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_dimensions(mANW.get(),
             texWidth, texHeight));
     ASSERT_EQ(NO_ERROR, native_window_set_buffers_format(mANW.get(),
@@ -436,7 +447,10 @@
         virtual bool threadLoop() {
             ANativeWindowBuffer* anb;
 
-            native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL);
+            if (native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU) !=
+                    NO_ERROR) {
+                return false;
+            }
 
             for (int numFrames =0 ; numFrames < 2; numFrames ++) {
 
@@ -453,7 +467,10 @@
                 }
             }
 
-            native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL);
+            if (native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU)
+                    != NO_ERROR) {
+                return false;
+            }
 
             return false;
         }
@@ -467,7 +484,7 @@
 
 
     sp<Thread> pt(new ProducerThread(mANW));
-    pt->run();
+    pt->run("ProducerThread");
 
     // eat a frame so GLConsumer will own an at least one slot
     dw->waitForFrame();
@@ -487,7 +504,7 @@
 // attempt to release a buffer that it does not owned
 TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) {
     ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
 
     ANativeWindowBuffer *anb;
 
@@ -501,9 +518,9 @@
     EXPECT_EQ(OK,mST->updateTexImage());
 
     ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(OK, native_window_api_connect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
 
     EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
     EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1));
@@ -513,7 +530,7 @@
     EXPECT_EQ(OK,mST->updateTexImage());
 
     ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(),
-            NATIVE_WINDOW_API_EGL));
+            NATIVE_WINDOW_API_CPU));
 }
 
 TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) {
@@ -615,6 +632,11 @@
             Mutex::Autolock lock(mMutex);
             ANativeWindowBuffer* anb;
 
+            if (native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU) !=
+                    NO_ERROR) {
+                return false;
+            }
+
             // Frame 1
             if (native_window_dequeue_buffer_and_wait(mANW.get(),
                     &anb) != NO_ERROR) {
@@ -658,10 +680,8 @@
         Mutex mMutex;
     };
 
-    ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2));
-
     sp<Thread> pt(new ProducerThread(mANW));
-    pt->run();
+    pt->run("ProducerThread");
 
     mFW->waitForFrame();
     mFW->waitForFrame();
@@ -681,6 +701,9 @@
     int texHeight = 16;
     ANativeWindowBuffer* anb;
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(mANW.get(),
+            NATIVE_WINDOW_API_CPU));
+
     GLint maxTextureSize;
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
 
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL.h b/libs/gui/tests/SurfaceTextureMultiContextGL.h
index 7934bbc..3cca035 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL.h
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL.h
@@ -27,7 +27,8 @@
     enum { THIRD_TEX_ID = 456 };
 
     SurfaceTextureMultiContextGLTest():
-            mSecondEglContext(EGL_NO_CONTEXT) {
+            mSecondEglContext(EGL_NO_CONTEXT),
+            mThirdEglContext(EGL_NO_CONTEXT) {
     }
 
     virtual void SetUp() {
diff --git a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
index 1cd101e..5b02dcf 100644
--- a/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
+++ b/libs/gui/tests/SurfaceTextureMultiContextGL_test.cpp
@@ -26,6 +26,7 @@
 namespace android {
 
 TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -40,6 +41,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -55,6 +57,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         DetachFromContextSucceedsAfterProducerDisconnect) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -70,6 +73,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -82,6 +86,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -96,6 +101,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -112,6 +118,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -128,6 +135,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -139,6 +147,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -169,6 +178,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsAfterProducerDisconnect) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -200,6 +210,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsBeforeUpdateTexImage) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -230,6 +241,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -247,6 +259,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -259,6 +272,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextFailsWhenAttachedBeforeUpdateTexImage) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Attempt to attach to the primary context.
@@ -266,6 +280,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -285,6 +300,7 @@
 }
 
 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Latch the texture contents on the primary context.
@@ -323,6 +339,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         AttachToContextSucceedsTwiceBeforeUpdateTexImage) {
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
 
     // Detach from the primary context.
@@ -361,7 +378,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
         UpdateTexImageSucceedsForBufferConsumedBeforeDetach) {
-    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
 
     // produce two frames and consume them both on the primary context
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
@@ -388,7 +405,7 @@
 
 TEST_F(SurfaceTextureMultiContextGLTest,
        AttachAfterDisplayTerminatedSucceeds) {
-    ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2));
+    ASSERT_EQ(OK, native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU));
 
     // produce two frames and consume them both on the primary context
     ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW));
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 3f495f8..0de60c9 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -100,6 +100,8 @@
     ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
             64, 64, 0, 0x7fffffff, false));
 
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
+            NATIVE_WINDOW_API_CPU));
     // Set the PROTECTED usage bit and verify that the screenshot fails.  Note
     // that we need to dequeue a buffer in order for it to actually get
     // allocated in SurfaceFlinger.
@@ -190,6 +192,8 @@
     // Allocate a buffer with a generation number of 0
     ANativeWindowBuffer* buffer;
     int fenceFd;
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(),
+            NATIVE_WINDOW_API_CPU));
     ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fenceFd));
     ASSERT_EQ(NO_ERROR, window->cancelBuffer(window.get(), buffer, fenceFd));
 
@@ -228,4 +232,30 @@
     EXPECT_STREQ("TestConsumer", surface->getConsumerName().string());
 }
 
+TEST_F(SurfaceTest, DynamicSetBufferCount) {
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+
+    sp<DummyConsumer> dummyConsumer(new DummyConsumer);
+    consumer->consumerConnect(dummyConsumer, false);
+    consumer->setConsumerName(String8("TestConsumer"));
+
+    sp<Surface> surface = new Surface(producer);
+    sp<ANativeWindow> window(surface);
+
+    ASSERT_EQ(NO_ERROR, native_window_api_connect(window.get(),
+            NATIVE_WINDOW_API_CPU));
+    native_window_set_buffer_count(window.get(), 4);
+
+    int fence;
+    ANativeWindowBuffer* buffer;
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    native_window_set_buffer_count(window.get(), 3);
+    ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+    native_window_set_buffer_count(window.get(), 2);
+    ASSERT_EQ(NO_ERROR, window->dequeueBuffer(window.get(), &buffer, &fence));
+    ASSERT_EQ(NO_ERROR, window->queueBuffer(window.get(), buffer, fence));
+}
+
 }
diff --git a/libs/gui/tests/TextureRenderer.cpp b/libs/gui/tests/TextureRenderer.cpp
index 90951b3..e822e6e 100644
--- a/libs/gui/tests/TextureRenderer.cpp
+++ b/libs/gui/tests/TextureRenderer.cpp
@@ -28,7 +28,8 @@
 namespace android {
 
 TextureRenderer::TextureRenderer(GLuint texName,
-        const sp<GLConsumer>& st) : mTexName(texName), mST(st) {
+        const sp<GLConsumer>& st) : mTexName(texName), mST(st), mPgm(0),
+        mPositionHandle(-1), mTexSamplerHandle(-1), mTexMatrixHandle(-1) {
 }
 
 void TextureRenderer::SetUp() {
diff --git a/libs/input/Android.mk b/libs/input/Android.mk
index 944ac7f..746de66 100644
--- a/libs/input/Android.mk
+++ b/libs/input/Android.mk
@@ -56,6 +56,9 @@
 
 LOCAL_SRC_FILES:= $(deviceSources)
 
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
 LOCAL_SHARED_LIBRARIES := \
 	liblog \
 	libcutils \
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index b64cb2c..a624663 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -23,7 +23,7 @@
 #include <input/Input.h>
 #include <input/InputEventLabels.h>
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
 #include <binder/Parcel.h>
 #endif
 
@@ -144,7 +144,7 @@
     setAxisValue(AMOTION_EVENT_AXIS_Y, getY() + yOffset);
 }
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
 status_t PointerCoords::readFromParcel(Parcel* parcel) {
     bits = parcel->readInt64();
 
@@ -420,7 +420,7 @@
     }
 }
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
 status_t MotionEvent::readFromParcel(Parcel* parcel) {
     size_t pointerCount = parcel->readInt32();
     size_t sampleCount = parcel->readInt32();
@@ -457,7 +457,8 @@
         properties.toolType = parcel->readInt32();
     }
 
-    while (sampleCount-- > 0) {
+    while (sampleCount > 0) {
+        sampleCount--;
         mSampleEventTimes.push(parcel->readInt64());
         for (size_t i = 0; i < pointerCount; i++) {
             mSamplePointerCoords.push();
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 7f83da5..2dff4e0 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -516,7 +516,8 @@
 status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
         nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
     status_t result;
-    for (size_t i = mBatches.size(); i-- > 0; ) {
+    for (size_t i = mBatches.size(); i > 0; ) {
+        i--;
         Batch& batch = mBatches.editItemAt(i);
         if (frameTime < 0) {
             result = consumeSamples(factory, batch, batch.samples.size(),
@@ -826,7 +827,8 @@
         uint32_t currentSeq = seq;
         uint32_t chainSeqs[seqChainCount];
         size_t chainIndex = 0;
-        for (size_t i = seqChainCount; i-- > 0; ) {
+        for (size_t i = seqChainCount; i > 0; ) {
+             i--;
              const SeqChain& seqChain = mSeqChains.itemAt(i);
              if (seqChain.seq == currentSeq) {
                  currentSeq = seqChain.chain;
@@ -835,7 +837,8 @@
              }
         }
         status_t status = OK;
-        while (!status && chainIndex-- > 0) {
+        while (!status && chainIndex > 0) {
+            chainIndex--;
             status = sendUnchainedFinishedSignal(chainSeqs[chainIndex], handled);
         }
         if (status) {
@@ -845,7 +848,10 @@
                 seqChain.seq = chainIndex != 0 ? chainSeqs[chainIndex - 1] : seq;
                 seqChain.chain = chainSeqs[chainIndex];
                 mSeqChains.push(seqChain);
-            } while (chainIndex-- > 0);
+                if (chainIndex != 0) {
+                    chainIndex--;
+                }
+            } while (chainIndex > 0);
             return status;
         }
     }
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index df3f0dd..0627ca6 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -19,7 +19,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#if HAVE_ANDROID_OS
+#ifdef __ANDROID__
 #include <binder/Parcel.h>
 #endif
 
@@ -599,7 +599,7 @@
     }
 }
 
-#if HAVE_ANDROID_OS
+#ifdef __ANDROID__
 sp<KeyCharacterMap> KeyCharacterMap::readFromParcel(Parcel* parcel) {
     sp<KeyCharacterMap> map = new KeyCharacterMap();
     map->mType = parcel->readInt32();
@@ -607,6 +607,10 @@
     if (parcel->errorCheck()) {
         return NULL;
     }
+    if (numKeys > MAX_KEYS) {
+        ALOGE("Too many keys in KeyCharacterMap (%zu > %d)", numKeys, MAX_KEYS);
+        return NULL;
+    }
 
     for (size_t i = 0; i < numKeys; i++) {
         int32_t keyCode = parcel->readInt32();
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 6c70c3c..7f6b157 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -46,7 +46,8 @@
 
 static float vectorDot(const float* a, const float* b, uint32_t m) {
     float r = 0;
-    while (m--) {
+    while (m) {
+        m--;
         r += *(a++) * *(b++);
     }
     return r;
@@ -54,7 +55,8 @@
 
 static float vectorNorm(const float* a, uint32_t m) {
     float r = 0;
-    while (m--) {
+    while (m) {
+        m--;
         float t = *(a++);
         r += t * t;
     }
@@ -511,7 +513,8 @@
     for (uint32_t h = 0; h < m; h++) {
         wy[h] = y[h] * w[h];
     }
-    for (uint32_t i = n; i-- != 0; ) {
+    for (uint32_t i = n; i != 0; ) {
+        i--;
         outB[i] = vectorDot(&q[i][0], wy, m);
         for (uint32_t j = n - 1; j > i; j--) {
             outB[i] -= r[i][j] * outB[j];
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index 1ce8626..ee6c093 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -17,6 +17,7 @@
 
 LOCAL_CLANG := true
 LOCAL_CPPFLAGS := -std=c++1y -Weverything -Werror
+LOCAL_SANITIZE := integer
 
 # The static constructors and destructors in this library have not been noted to
 # introduce significant overheads
@@ -35,17 +36,18 @@
 
 LOCAL_SRC_FILES := \
 	Fence.cpp \
-	FramebufferNativeWindow.cpp \
 	FrameStats.cpp \
 	GraphicBuffer.cpp \
 	GraphicBufferAllocator.cpp \
 	GraphicBufferMapper.cpp \
+	HdrCapabilities.cpp \
 	PixelFormat.cpp \
 	Rect.cpp \
 	Region.cpp \
 	UiConfig.cpp
 
 LOCAL_SHARED_LIBRARIES := \
+	libbinder \
 	libcutils \
 	libhardware \
 	libsync \
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
deleted file mode 100644
index 3ead25c..0000000
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
-**
-** Copyright 2007 The Android Open Source Project
-**
-** 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.
-*/
-
-#define LOG_TAG "FramebufferNativeWindow"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-
-#include <cutils/log.h>
-#include <cutils/atomic.h>
-#include <utils/threads.h>
-#include <utils/RefBase.h>
-
-#include <ui/ANativeObjectBase.h>
-#include <ui/Fence.h>
-#define INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
-#include <ui/FramebufferNativeWindow.h>
-#undef INCLUDED_FROM_FRAMEBUFFER_NATIVE_WINDOW_CPP
-#include <ui/Rect.h>
-
-#include <EGL/egl.h>
-
-#include <hardware/hardware.h>
-#include <hardware/gralloc.h>
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-class NativeBuffer final
-    : public ANativeObjectBase<
-        ANativeWindowBuffer,
-        NativeBuffer,
-        LightRefBase<NativeBuffer>>
-{
-public:
-    NativeBuffer(int w, int h, int f, int u) : BASE() {
-        ANativeWindowBuffer::width  = w;
-        ANativeWindowBuffer::height = h;
-        ANativeWindowBuffer::format = f;
-        ANativeWindowBuffer::usage  = u;
-    }
-private:
-    friend class LightRefBase<NativeBuffer>;
-};
-
-
-/*
- * This implements the (main) framebuffer management. This class is used
- * mostly by SurfaceFlinger, but also by command line GL application.
- *
- * In fact this is an implementation of ANativeWindow on top of
- * the framebuffer.
- *
- * Currently it is pretty simple, it manages only two buffers (the front and
- * back buffer).
- *
- */
-
-FramebufferNativeWindow::FramebufferNativeWindow()
-    : BASE(), fbDev(0), grDev(0), mUpdateOnDemand(false)
-{
-    hw_module_t const* module;
-    if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
-        int err;
-        int i;
-        err = framebuffer_open(module, &fbDev);
-        ALOGE_IF(err, "couldn't open framebuffer HAL (%s)", strerror(-err));
-
-        err = gralloc_open(module, &grDev);
-        ALOGE_IF(err, "couldn't open gralloc HAL (%s)", strerror(-err));
-
-        // bail out if we can't initialize the modules
-        if (!fbDev || !grDev)
-            return;
-
-        mUpdateOnDemand = (fbDev->setUpdateRect != 0);
-
-        // initialize the buffer FIFO
-        if(fbDev->numFramebuffers >= MIN_NUM_FRAME_BUFFERS &&
-           fbDev->numFramebuffers <= MAX_NUM_FRAME_BUFFERS){
-            mNumBuffers = fbDev->numFramebuffers;
-        } else {
-            mNumBuffers = MIN_NUM_FRAME_BUFFERS;
-        }
-        mNumFreeBuffers = mNumBuffers;
-        mBufferHead = mNumBuffers-1;
-
-        /*
-         * This does not actually change the framebuffer format. It merely
-         * fakes this format to surfaceflinger so that when it creates
-         * framebuffer surfaces it will use this format. It's really a giant
-         * HACK to allow interworking with buggy gralloc+GPU driver
-         * implementations. You should *NEVER* need to set this for shipping
-         * devices.
-         */
-#ifdef FRAMEBUFFER_FORCE_FORMAT
-        *((uint32_t *)&fbDev->format) = FRAMEBUFFER_FORCE_FORMAT;
-#endif
-
-        for (i = 0; i < mNumBuffers; i++) {
-            buffers[i] = new NativeBuffer(
-                    static_cast<int>(fbDev->width),
-                    static_cast<int>(fbDev->height),
-                    fbDev->format, GRALLOC_USAGE_HW_FB);
-        }
-
-        for (i = 0; i < mNumBuffers; i++) {
-            err = grDev->alloc(grDev,
-                    static_cast<int>(fbDev->width),
-                    static_cast<int>(fbDev->height),
-                    fbDev->format, GRALLOC_USAGE_HW_FB,
-                    &buffers[i]->handle, &buffers[i]->stride);
-
-            ALOGE_IF(err, "fb buffer %d allocation failed w=%d, h=%d, err=%s",
-                    i, fbDev->width, fbDev->height, strerror(-err));
-
-            if (err) {
-                mNumBuffers = i;
-                mNumFreeBuffers = i;
-                mBufferHead = mNumBuffers-1;
-                break;
-            }
-        }
-
-        const_cast<uint32_t&>(ANativeWindow::flags) = fbDev->flags;
-        const_cast<float&>(ANativeWindow::xdpi) = fbDev->xdpi;
-        const_cast<float&>(ANativeWindow::ydpi) = fbDev->ydpi;
-        const_cast<int&>(ANativeWindow::minSwapInterval) =
-            fbDev->minSwapInterval;
-        const_cast<int&>(ANativeWindow::maxSwapInterval) =
-            fbDev->maxSwapInterval;
-    } else {
-        ALOGE("Couldn't get gralloc module");
-    }
-
-    ANativeWindow::setSwapInterval = setSwapInterval;
-    ANativeWindow::dequeueBuffer = dequeueBuffer;
-    ANativeWindow::queueBuffer = queueBuffer;
-    ANativeWindow::query = query;
-    ANativeWindow::perform = perform;
-
-    ANativeWindow::dequeueBuffer_DEPRECATED = dequeueBuffer_DEPRECATED;
-    ANativeWindow::lockBuffer_DEPRECATED = lockBuffer_DEPRECATED;
-    ANativeWindow::queueBuffer_DEPRECATED = queueBuffer_DEPRECATED;
-}
-
-FramebufferNativeWindow::~FramebufferNativeWindow()
-{
-    if (grDev) {
-        for(int i = 0; i < mNumBuffers; i++) {
-            if (buffers[i] != NULL) {
-                grDev->free(grDev, buffers[i]->handle);
-            }
-        }
-        gralloc_close(grDev);
-    }
-
-    if (fbDev) {
-        framebuffer_close(fbDev);
-    }
-}
-
-status_t FramebufferNativeWindow::setUpdateRectangle(const Rect& r)
-{
-    if (!mUpdateOnDemand) {
-        return INVALID_OPERATION;
-    }
-    return fbDev->setUpdateRect(fbDev, r.left, r.top, r.width(), r.height());
-}
-
-status_t FramebufferNativeWindow::compositionComplete()
-{
-    if (fbDev->compositionComplete) {
-        return fbDev->compositionComplete(fbDev);
-    }
-    return INVALID_OPERATION;
-}
-
-int FramebufferNativeWindow::setSwapInterval(
-        ANativeWindow* window, int interval)
-{
-    framebuffer_device_t* fb = getSelf(window)->fbDev;
-    return fb->setSwapInterval(fb, interval);
-}
-
-void FramebufferNativeWindow::dump(String8& result) {
-    if (fbDev->common.version >= 1 && fbDev->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-
-        fbDev->dump(fbDev, buffer, SIZE);
-        result.append(buffer);
-    }
-}
-
-// only for debugging / logging
-int FramebufferNativeWindow::getCurrentBufferIndex() const
-{
-    Mutex::Autolock _l(mutex);
-    const int index = mCurrentBufferIndex;
-    return index;
-}
-
-int FramebufferNativeWindow::dequeueBuffer_DEPRECATED(ANativeWindow* window,
-        ANativeWindowBuffer** buffer)
-{
-    int fenceFd = -1;
-    int result = dequeueBuffer(window, buffer, &fenceFd);
-    sp<Fence> fence(new Fence(fenceFd));
-    int waitResult = fence->wait(Fence::TIMEOUT_NEVER);
-    if (waitResult != OK) {
-        ALOGE("dequeueBuffer_DEPRECATED: Fence::wait returned an "
-                "error: %d", waitResult);
-        return waitResult;
-    }
-    return result;
-}
-
-int FramebufferNativeWindow::dequeueBuffer(ANativeWindow* window,
-        ANativeWindowBuffer** buffer, int* fenceFd)
-{
-    FramebufferNativeWindow* self = getSelf(window);
-    Mutex::Autolock _l(self->mutex);
-
-    int index = self->mBufferHead++;
-    if (self->mBufferHead >= self->mNumBuffers)
-        self->mBufferHead = 0;
-
-    // wait for a free non-front buffer
-    while (self->mNumFreeBuffers < 2) {
-        self->mCondition.wait(self->mutex);
-    }
-    ALOG_ASSERT(self->buffers[index] != self->front, "");
-
-    // get this buffer
-    self->mNumFreeBuffers--;
-    self->mCurrentBufferIndex = index;
-
-    *buffer = self->buffers[index].get();
-    *fenceFd = -1;
-
-    return 0;
-}
-
-int FramebufferNativeWindow::lockBuffer_DEPRECATED(ANativeWindow* /*window*/,
-        ANativeWindowBuffer* /*buffer*/)
-{
-    return NO_ERROR;
-}
-
-int FramebufferNativeWindow::queueBuffer_DEPRECATED(ANativeWindow* window,
-        ANativeWindowBuffer* buffer)
-{
-    return queueBuffer(window, buffer, -1);
-}
-
-int FramebufferNativeWindow::queueBuffer(ANativeWindow* window,
-        ANativeWindowBuffer* buffer, int fenceFd)
-{
-    FramebufferNativeWindow* self = getSelf(window);
-    Mutex::Autolock _l(self->mutex);
-    framebuffer_device_t* fb = self->fbDev;
-    buffer_handle_t handle = static_cast<NativeBuffer*>(buffer)->handle;
-
-    sp<Fence> fence(new Fence(fenceFd));
-    fence->wait(Fence::TIMEOUT_NEVER);
-
-    int res = fb->post(fb, handle);
-    self->front = static_cast<NativeBuffer*>(buffer);
-    self->mNumFreeBuffers++;
-    self->mCondition.broadcast();
-    return res;
-}
-
-int FramebufferNativeWindow::query(const ANativeWindow* window,
-        int what, int* value)
-{
-    const FramebufferNativeWindow* self = getSelf(window);
-    Mutex::Autolock _l(self->mutex);
-    framebuffer_device_t* fb = self->fbDev;
-    switch (what) {
-        case NATIVE_WINDOW_WIDTH:
-            *value = static_cast<int>(fb->width);
-            return NO_ERROR;
-        case NATIVE_WINDOW_HEIGHT:
-            *value = static_cast<int>(fb->height);
-            return NO_ERROR;
-        case NATIVE_WINDOW_FORMAT:
-            *value = fb->format;
-            return NO_ERROR;
-        case NATIVE_WINDOW_CONCRETE_TYPE:
-            *value = NATIVE_WINDOW_FRAMEBUFFER;
-            return NO_ERROR;
-        case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
-            *value = 0;
-            return NO_ERROR;
-        case NATIVE_WINDOW_DEFAULT_WIDTH:
-            *value = static_cast<int>(fb->width);
-            return NO_ERROR;
-        case NATIVE_WINDOW_DEFAULT_HEIGHT:
-            *value = static_cast<int>(fb->height);
-            return NO_ERROR;
-        case NATIVE_WINDOW_TRANSFORM_HINT:
-            *value = 0;
-            return NO_ERROR;
-    }
-    *value = 0;
-    return BAD_VALUE;
-}
-
-int FramebufferNativeWindow::perform(ANativeWindow* /*window*/,
-        int operation, ...)
-{
-    switch (operation) {
-        case NATIVE_WINDOW_CONNECT:
-        case NATIVE_WINDOW_DISCONNECT:
-        case NATIVE_WINDOW_SET_USAGE:
-        case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
-        case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
-        case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
-        case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
-        case NATIVE_WINDOW_API_CONNECT:
-        case NATIVE_WINDOW_API_DISCONNECT:
-            // TODO: we should implement these
-            return NO_ERROR;
-
-        case NATIVE_WINDOW_LOCK:
-        case NATIVE_WINDOW_UNLOCK_AND_POST:
-        case NATIVE_WINDOW_SET_CROP:
-        case NATIVE_WINDOW_SET_BUFFER_COUNT:
-        case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
-        case NATIVE_WINDOW_SET_SCALING_MODE:
-            return INVALID_OPERATION;
-    }
-    return NAME_NOT_FOUND;
-}
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
-
-using android::sp;
-using android::FramebufferNativeWindow;
-
-EGLNativeWindowType android_createDisplaySurface(void)
-{
-    FramebufferNativeWindow* w;
-    w = new FramebufferNativeWindow();
-    if (w->getDevice() == NULL) {
-        // get a ref so it can be destroyed when we exit this block
-        sp<FramebufferNativeWindow> ref(w);
-        return NULL;
-    }
-    return static_cast<EGLNativeWindowType>(w);
-}
diff --git a/libs/ui/GraphicBuffer.cpp b/libs/ui/GraphicBuffer.cpp
index e55db30..4fe0946 100644
--- a/libs/ui/GraphicBuffer.cpp
+++ b/libs/ui/GraphicBuffer.cpp
@@ -43,7 +43,7 @@
 
 GraphicBuffer::GraphicBuffer()
     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR), mId(getUniqueId())
+      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
 {
     width  =
     height =
@@ -56,7 +56,7 @@
 GraphicBuffer::GraphicBuffer(uint32_t inWidth, uint32_t inHeight,
         PixelFormat inFormat, uint32_t inUsage)
     : BASE(), mOwner(ownData), mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR), mId(getUniqueId())
+      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
 {
     width  =
     height =
@@ -72,7 +72,7 @@
         native_handle_t* inHandle, bool keepOwnership)
     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
       mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR), mId(getUniqueId())
+      mInitCheck(NO_ERROR), mId(getUniqueId()), mGenerationNumber(0)
 {
     width  = static_cast<int>(inWidth);
     height = static_cast<int>(inHeight);
@@ -85,7 +85,8 @@
 GraphicBuffer::GraphicBuffer(ANativeWindowBuffer* buffer, bool keepOwnership)
     : BASE(), mOwner(keepOwnership ? ownHandle : ownNone),
       mBufferMapper(GraphicBufferMapper::get()),
-      mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId())
+      mInitCheck(NO_ERROR), mWrappedBuffer(buffer), mId(getUniqueId()),
+      mGenerationNumber(0)
 {
     width  = buffer->width;
     height = buffer->height;
@@ -112,6 +113,7 @@
         GraphicBufferAllocator& allocator(GraphicBufferAllocator::get());
         allocator.free(handle);
     }
+    handle = NULL;
     mWrappedBuffer = 0;
 }
 
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
new file mode 100644
index 0000000..511f68a
--- /dev/null
+++ b/libs/ui/HdrCapabilities.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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 <ui/HdrCapabilities.h>
+
+#include <binder/Parcel.h>
+
+namespace android {
+
+status_t HdrCapabilities::writeToParcel(Parcel* parcel) const
+{
+    status_t result = parcel->writeInt32Vector(mSupportedHdrTypes);
+    if (result != OK) {
+        return result;
+    }
+    result = parcel->writeFloat(mMaxLuminance);
+    if (result != OK) {
+        return result;
+    }
+    result = parcel->writeFloat(mMaxAverageLuminance);
+    if (result != OK) {
+        return result;
+    }
+    result = parcel->writeFloat(mMinLuminance);
+    return result;
+}
+
+status_t HdrCapabilities::readFromParcel(const Parcel* parcel)
+{
+    status_t result = parcel->readInt32Vector(&mSupportedHdrTypes);
+    if (result != OK) {
+        return result;
+    }
+    result = parcel->readFloat(&mMaxLuminance);
+    if (result != OK) {
+        return result;
+    }
+    result = parcel->readFloat(&mMaxAverageLuminance);
+    if (result != OK) {
+        return result;
+    }
+    result = parcel->readFloat(&mMinLuminance);
+    return result;
+}
+
+} // namespace android
diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp
index dcce21f..d8702e5 100644
--- a/libs/ui/Rect.cpp
+++ b/libs/ui/Rect.cpp
@@ -20,6 +20,7 @@
 namespace android {
 
 const Rect Rect::INVALID_RECT{0, 0, -1, -1};
+const Rect Rect::EMPTY_RECT{0, 0, 0, 0};
 
 static inline int32_t min(int32_t a, int32_t b) {
     return (a < b) ? a : b;
@@ -110,7 +111,7 @@
 }
 
 Rect Rect::reduce(const Rect& exclude) const {
-    Rect result;
+    Rect result(Rect::EMPTY_RECT);
 
     uint32_t mask = 0;
     mask |= (exclude.left   > left)   ? 1 : 0;
@@ -126,13 +127,13 @@
         if (!(mask & (mask - 1))) {
             // power-of-2, i.e.: just one bit is set
             if (mask & 1) {
-                result.right = exclude.left;
+                result.right = min(result.right, exclude.left);
             } else if (mask & 2) {
-                result.bottom = exclude.top;
+                result.bottom = min(result.bottom, exclude.top);
             } else if (mask & 4) {
-                result.left = exclude.right;
+                result.left = max(result.left, exclude.right);
             } else if (mask & 8) {
-                result.top = exclude.bottom;
+                result.top = max(result.top, exclude.bottom);
             }
         }
     }
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp
index 3810da4..ac37990 100644
--- a/libs/ui/Region.cpp
+++ b/libs/ui/Region.cpp
@@ -798,7 +798,7 @@
     Region result;
     result.mStorage.clear();
     for (size_t r = 0; r < numRects; ++r) {
-        Rect rect;
+        Rect rect(Rect::EMPTY_RECT);
         status_t status = rect.unflatten(buffer, size);
         if (status != NO_ERROR) {
             return status;
@@ -835,18 +835,6 @@
     return begin();
 }
 
-SharedBuffer const* Region::getSharedBuffer(size_t* count) const {
-    // We can get to the SharedBuffer of a Vector<Rect> because Rect has
-    // a trivial destructor.
-    SharedBuffer const* sb = SharedBuffer::bufferFromData(mStorage.array());
-    if (count) {
-        size_t numRects = isRect() ? 1 : mStorage.size() - 1;
-        count[0] = numRects;
-    }
-    sb->acquire();
-    return sb;
-}
-
 // ----------------------------------------------------------------------------
 
 void Region::dump(String8& out, const char* what, uint32_t /* flags */) const
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index b2abdb1..bef5f02 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -598,6 +598,29 @@
 #endif
 #endif
 
+#ifndef EGL_ANDROID_create_native_client_buffer
+#define EGL_ANDROID_create_native_client_buffer 1
+#define EGL_NATIVE_BUFFER_USAGE_ANDROID   0x3143
+#define EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID   0x00000001
+#define EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID   0x00000002
+#define EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID   0x00000004
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLClientBuffer eglCreateNativeClientBufferANDROID (const EGLint *attrib_list);
+#else
+typedef EGLAPI EGLClientBuffer (EGLAPIENTRYP PFNEGLCREATENATIVECLIENTBUFFERANDROID) (const EGLint *attrib_list);
+#endif
+#endif
+
+#ifndef EGL_ANDROID_front_buffer_auto_refresh
+#define EGL_ANDROID_front_buffer_auto_refresh 1
+#define EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+#endif
+
+#ifndef EGL_KHR_mutable_render_buffer
+#define EGL_KHR_mutable_render_buffer 1
+#define EGL_MUTABLE_RENDER_BUFFER_BIT_KHR 0x1000
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/include/GLES2/gl2.h b/opengl/include/GLES2/gl2.h
index 8a4d43a..f64ec00 100644
--- a/opengl/include/GLES2/gl2.h
+++ b/opengl/include/GLES2/gl2.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -33,12 +33,20 @@
 ** used to make the header, and the header can be found at
 **   http://www.opengl.org/registry/
 **
-** Khronos $Revision: 26696 $ on $Date: 2014-05-17 14:48:55 -0700 (Sat, 17 May 2014) $
+** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
 */
 
 #include <GLES2/gl2platform.h>
 
-/* Generated on date 20140517 */
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
 
 /* Generated C header for:
  * API: gles2
@@ -374,6 +382,149 @@
 #define GL_RENDERBUFFER_BINDING           0x8CA7
 #define GL_MAX_RENDERBUFFER_SIZE          0x84E8
 #define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
 GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
 GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
 GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -516,6 +667,7 @@
 GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
 GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
 GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
 #endif /* GL_ES_VERSION_2_0 */
 
 #ifdef __cplusplus
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index 9749f9f..2d05596 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -33,14 +33,14 @@
 ** used to make the header, and the header can be found at
 **   http://www.opengl.org/registry/
 **
-** Khronos $Revision$ on $Date$
+** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
 */
 
 #ifndef GL_APIENTRYP
 #define GL_APIENTRYP GL_APIENTRY*
 #endif
 
-/* Generated on date 20140519 */
+/* Generated on date 20151015 */
 
 /* Generated C header for:
  * API: gles2
@@ -54,7 +54,6 @@
 
 #ifndef GL_KHR_blend_equation_advanced
 #define GL_KHR_blend_equation_advanced 1
-#define GL_BLEND_ADVANCED_COHERENT_KHR    0x9285
 #define GL_MULTIPLY_KHR                   0x9294
 #define GL_SCREEN_KHR                     0x9295
 #define GL_OVERLAY_KHR                    0x9296
@@ -76,6 +75,17 @@
 #endif
 #endif /* GL_KHR_blend_equation_advanced */
 
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR    0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
+
+#ifndef GL_KHR_context_flush_control
+#define GL_KHR_context_flush_control 1
+#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR   0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC
+#endif /* GL_KHR_context_flush_control */
+
 #ifndef GL_KHR_debug
 #define GL_KHR_debug 1
 typedef void (GL_APIENTRY  *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
@@ -107,6 +117,7 @@
 #define GL_PROGRAM_KHR                    0x82E2
 #define GL_VERTEX_ARRAY_KHR               0x8074
 #define GL_QUERY_KHR                      0x82E3
+#define GL_PROGRAM_PIPELINE_KHR           0x82E4
 #define GL_SAMPLER_KHR                    0x82E6
 #define GL_MAX_LABEL_LENGTH_KHR           0x82E8
 #define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR   0x9143
@@ -145,6 +156,39 @@
 #endif
 #endif /* GL_KHR_debug */
 
+#ifndef GL_KHR_no_error
+#define GL_KHR_no_error 1
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR  0x00000008
+#endif /* GL_KHR_no_error */
+
+#ifndef GL_KHR_robust_buffer_access_behavior
+#define GL_KHR_robust_buffer_access_behavior 1
+#endif /* GL_KHR_robust_buffer_access_behavior */
+
+#ifndef GL_KHR_robustness
+#define GL_KHR_robustness 1
+#define GL_CONTEXT_ROBUST_ACCESS_KHR      0x90F3
+#define GL_LOSE_CONTEXT_ON_RESET_KHR      0x8252
+#define GL_GUILTY_CONTEXT_RESET_KHR       0x8253
+#define GL_INNOCENT_CONTEXT_RESET_KHR     0x8254
+#define GL_UNKNOWN_CONTEXT_RESET_KHR      0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256
+#define GL_NO_RESET_NOTIFICATION_KHR      0x8261
+#define GL_CONTEXT_LOST_KHR               0x0507
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void);
+GL_APICALL void GL_APIENTRY glReadnPixelsKHR (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfvKHR (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformivKHR (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+#endif
+#endif /* GL_KHR_robustness */
+
 #ifndef GL_KHR_texture_compression_astc_hdr
 #define GL_KHR_texture_compression_astc_hdr 1
 #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR   0x93B0
@@ -181,6 +225,10 @@
 #define GL_KHR_texture_compression_astc_ldr 1
 #endif /* GL_KHR_texture_compression_astc_ldr */
 
+#ifndef GL_KHR_texture_compression_astc_sliced_3d
+#define GL_KHR_texture_compression_astc_sliced_3d 1
+#endif /* GL_KHR_texture_compression_astc_sliced_3d */
+
 #ifndef GL_OES_EGL_image
 #define GL_OES_EGL_image 1
 typedef void *GLeglImageOES;
@@ -200,6 +248,14 @@
 #define GL_SAMPLER_EXTERNAL_OES           0x8D66
 #endif /* GL_OES_EGL_image_external */
 
+#ifndef GL_OES_EGL_image_external_essl3
+#define GL_OES_EGL_image_external_essl3 1
+#endif /* GL_OES_EGL_image_external_essl3 */
+
+#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture
+#define GL_OES_compressed_ETC1_RGB8_sub_texture 1
+#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */
+
 #ifndef GL_OES_compressed_ETC1_RGB8_texture
 #define GL_OES_compressed_ETC1_RGB8_texture 1
 #define GL_ETC1_RGB8_OES                  0x8D64
@@ -219,6 +275,14 @@
 #define GL_PALETTE8_RGB5_A1_OES           0x8B99
 #endif /* GL_OES_compressed_paletted_texture */
 
+#ifndef GL_OES_copy_image
+#define GL_OES_copy_image 1
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAOESPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCopyImageSubDataOES (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+#endif
+#endif /* GL_OES_copy_image */
+
 #ifndef GL_OES_depth24
 #define GL_OES_depth24 1
 #define GL_DEPTH_COMPONENT24_OES          0x81A6
@@ -233,6 +297,44 @@
 #define GL_OES_depth_texture 1
 #endif /* GL_OES_depth_texture */
 
+#ifndef GL_OES_draw_buffers_indexed
+#define GL_OES_draw_buffers_indexed 1
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+typedef void (GL_APIENTRYP PFNGLENABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIOESPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIOESPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIOESPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIOESPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIOESPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIOESPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIOESPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glEnableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiOES (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationiOES (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparateiOES (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunciOES (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparateiOES (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaskiOES (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediOES (GLenum target, GLuint index);
+#endif
+#endif /* GL_OES_draw_buffers_indexed */
+
+#ifndef GL_OES_draw_elements_base_vertex
+#define GL_OES_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXOESPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXOESPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexOES (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexOES (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_OES_draw_elements_base_vertex */
+
 #ifndef GL_OES_element_index_uint
 #define GL_OES_element_index_uint 1
 #endif /* GL_OES_element_index_uint */
@@ -245,6 +347,51 @@
 #define GL_OES_fragment_precision_high 1
 #endif /* GL_OES_fragment_precision_high */
 
+#ifndef GL_OES_geometry_point_size
+#define GL_OES_geometry_point_size 1
+#endif /* GL_OES_geometry_point_size */
+
+#ifndef GL_OES_geometry_shader
+#define GL_OES_geometry_shader 1
+#define GL_GEOMETRY_SHADER_OES            0x8DD9
+#define GL_GEOMETRY_SHADER_BIT_OES        0x00000004
+#define GL_GEOMETRY_LINKED_VERTICES_OUT_OES 0x8916
+#define GL_GEOMETRY_LINKED_INPUT_TYPE_OES 0x8917
+#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES 0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS_OES 0x887F
+#define GL_LAYER_PROVOKING_VERTEX_OES     0x825E
+#define GL_LINES_ADJACENCY_OES            0x000A
+#define GL_LINE_STRIP_ADJACENCY_OES       0x000B
+#define GL_TRIANGLES_ADJACENCY_OES        0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY_OES   0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES 0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES 0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES 0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES 0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION_OES    0x8E4D
+#define GL_LAST_VERTEX_CONVENTION_OES     0x8E4E
+#define GL_UNDEFINED_VERTEX_OES           0x8260
+#define GL_PRIMITIVES_GENERATED_OES       0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS_OES 0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS_OES     0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER_OES 0x9309
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREOESPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureOES (GLenum target, GLenum attachment, GLuint texture, GLint level);
+#endif
+#endif /* GL_OES_geometry_shader */
+
 #ifndef GL_OES_get_program_binary
 #define GL_OES_get_program_binary 1
 #define GL_PROGRAM_BINARY_LENGTH_OES      0x8741
@@ -258,6 +405,10 @@
 #endif
 #endif /* GL_OES_get_program_binary */
 
+#ifndef GL_OES_gpu_shader5
+#define GL_OES_gpu_shader5 1
+#endif /* GL_OES_gpu_shader5 */
+
 #ifndef GL_OES_mapbuffer
 #define GL_OES_mapbuffer 1
 #define GL_WRITE_ONLY_OES                 0x88B9
@@ -281,6 +432,15 @@
 #define GL_DEPTH24_STENCIL8_OES           0x88F0
 #endif /* GL_OES_packed_depth_stencil */
 
+#ifndef GL_OES_primitive_bounding_box
+#define GL_OES_primitive_bounding_box 1
+#define GL_PRIMITIVE_BOUNDING_BOX_OES     0x92BE
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXOESPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxOES (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+#endif
+#endif /* GL_OES_primitive_bounding_box */
+
 #ifndef GL_OES_required_internalformat
 #define GL_OES_required_internalformat 1
 #define GL_ALPHA8_OES                     0x803C
@@ -319,6 +479,10 @@
 #define GL_OES_shader_image_atomic 1
 #endif /* GL_OES_shader_image_atomic */
 
+#ifndef GL_OES_shader_io_blocks
+#define GL_OES_shader_io_blocks 1
+#endif /* GL_OES_shader_io_blocks */
+
 #ifndef GL_OES_shader_multisample_interpolation
 #define GL_OES_shader_multisample_interpolation 1
 #define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B
@@ -346,6 +510,61 @@
 #define GL_FRAMEBUFFER_UNDEFINED_OES      0x8219
 #endif /* GL_OES_surfaceless_context */
 
+#ifndef GL_OES_tessellation_point_size
+#define GL_OES_tessellation_point_size 1
+#endif /* GL_OES_tessellation_point_size */
+
+#ifndef GL_OES_tessellation_shader
+#define GL_OES_tessellation_shader 1
+#define GL_PATCHES_OES                    0x000E
+#define GL_PATCH_VERTICES_OES             0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES_OES 0x8E75
+#define GL_TESS_GEN_MODE_OES              0x8E76
+#define GL_TESS_GEN_SPACING_OES           0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER_OES      0x8E78
+#define GL_TESS_GEN_POINT_MODE_OES        0x8E79
+#define GL_ISOLINES_OES                   0x8E7A
+#define GL_QUADS_OES                      0x0007
+#define GL_FRACTIONAL_ODD_OES             0x8E7B
+#define GL_FRACTIONAL_EVEN_OES            0x8E7C
+#define GL_MAX_PATCH_VERTICES_OES         0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL_OES         0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS_OES  0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES 0x8221
+#define GL_IS_PER_PATCH_OES               0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES 0x9308
+#define GL_TESS_CONTROL_SHADER_OES        0x8E88
+#define GL_TESS_EVALUATION_SHADER_OES     0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT_OES    0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT_OES 0x00000010
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIOESPROC) (GLenum pname, GLint value);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPatchParameteriOES (GLenum pname, GLint value);
+#endif
+#endif /* GL_OES_tessellation_shader */
+
 #ifndef GL_OES_texture_3D
 #define GL_OES_texture_3D 1
 #define GL_TEXTURE_WRAP_R_OES             0x8072
@@ -370,6 +589,54 @@
 #endif
 #endif /* GL_OES_texture_3D */
 
+#ifndef GL_OES_texture_border_clamp
+#define GL_OES_texture_border_clamp 1
+#define GL_TEXTURE_BORDER_COLOR_OES       0x1004
+#define GL_CLAMP_TO_BORDER_OES            0x812D
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVOESPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVOESPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVOESPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVOESPROC) (GLuint sampler, GLenum pname, GLuint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexParameterIivOES (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuivOES (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIivOES (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuivOES (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIivOES (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuivOES (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIivOES (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivOES (GLuint sampler, GLenum pname, GLuint *params);
+#endif
+#endif /* GL_OES_texture_border_clamp */
+
+#ifndef GL_OES_texture_buffer
+#define GL_OES_texture_buffer 1
+#define GL_TEXTURE_BUFFER_OES             0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING_OES     0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE_OES    0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER_OES     0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES 0x919F
+#define GL_SAMPLER_BUFFER_OES             0x8DC2
+#define GL_INT_SAMPLER_BUFFER_OES         0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER_OES 0x8DD8
+#define GL_IMAGE_BUFFER_OES               0x9051
+#define GL_INT_IMAGE_BUFFER_OES           0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER_OES  0x9067
+#define GL_TEXTURE_BUFFER_OFFSET_OES      0x919D
+#define GL_TEXTURE_BUFFER_SIZE_OES        0x919E
+typedef void (GL_APIENTRYP PFNGLTEXBUFFEROESPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEOESPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexBufferOES (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRangeOES (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+#endif
+#endif /* GL_OES_texture_buffer */
+
 #ifndef GL_OES_texture_compression_astc
 #define GL_OES_texture_compression_astc 1
 #define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0
@@ -394,6 +661,19 @@
 #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9
 #endif /* GL_OES_texture_compression_astc */
 
+#ifndef GL_OES_texture_cube_map_array
+#define GL_OES_texture_cube_map_array 1
+#define GL_TEXTURE_CUBE_MAP_ARRAY_OES     0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY_OES     0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES 0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY_OES       0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY_OES   0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES 0x906A
+#endif /* GL_OES_texture_cube_map_array */
+
 #ifndef GL_OES_texture_float
 #define GL_OES_texture_float 1
 #endif /* GL_OES_texture_float */
@@ -434,6 +714,19 @@
 #endif
 #endif /* GL_OES_texture_storage_multisample_2d_array */
 
+#ifndef GL_OES_texture_view
+#define GL_OES_texture_view 1
+#define GL_TEXTURE_VIEW_MIN_LEVEL_OES     0x82DB
+#define GL_TEXTURE_VIEW_NUM_LEVELS_OES    0x82DC
+#define GL_TEXTURE_VIEW_MIN_LAYER_OES     0x82DD
+#define GL_TEXTURE_VIEW_NUM_LAYERS_OES    0x82DE
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWOESPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTextureViewOES (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+#endif
+#endif /* GL_OES_texture_view */
+
 #ifndef GL_OES_vertex_array_object
 #define GL_OES_vertex_array_object 1
 #define GL_VERTEX_ARRAY_BINDING_OES       0x85B5
@@ -512,6 +805,10 @@
 #define GL_Z400_BINARY_AMD                0x8740
 #endif /* GL_AMD_program_binary_Z400 */
 
+#ifndef GL_ANDROID_extension_pack_es31a
+#define GL_ANDROID_extension_pack_es31a 1
+#endif /* GL_ANDROID_extension_pack_es31a */
+
 #ifndef GL_ANGLE_depth_texture
 #define GL_ANGLE_depth_texture 1
 #endif /* GL_ANGLE_depth_texture */
@@ -587,6 +884,23 @@
 #endif
 #endif /* GL_ANGLE_translated_shader_source */
 
+#ifndef GL_APPLE_clip_distance
+#define GL_APPLE_clip_distance 1
+#define GL_MAX_CLIP_DISTANCES_APPLE       0x0D32
+#define GL_CLIP_DISTANCE0_APPLE           0x3000
+#define GL_CLIP_DISTANCE1_APPLE           0x3001
+#define GL_CLIP_DISTANCE2_APPLE           0x3002
+#define GL_CLIP_DISTANCE3_APPLE           0x3003
+#define GL_CLIP_DISTANCE4_APPLE           0x3004
+#define GL_CLIP_DISTANCE5_APPLE           0x3005
+#define GL_CLIP_DISTANCE6_APPLE           0x3006
+#define GL_CLIP_DISTANCE7_APPLE           0x3007
+#endif /* GL_APPLE_clip_distance */
+
+#ifndef GL_APPLE_color_buffer_packed_float
+#define GL_APPLE_color_buffer_packed_float 1
+#endif /* GL_APPLE_color_buffer_packed_float */
+
 #ifndef GL_APPLE_copy_texture_levels
 #define GL_APPLE_copy_texture_levels 1
 typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
@@ -667,6 +981,14 @@
 #define GL_TEXTURE_MAX_LEVEL_APPLE        0x813D
 #endif /* GL_APPLE_texture_max_level */
 
+#ifndef GL_APPLE_texture_packed_float
+#define GL_APPLE_texture_packed_float 1
+#define GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B
+#define GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E
+#define GL_R11F_G11F_B10F_APPLE           0x8C3A
+#define GL_RGB9_E5_APPLE                  0x8C3D
+#endif /* GL_APPLE_texture_packed_float */
+
 #ifndef GL_ARM_mali_program_binary
 #define GL_ARM_mali_program_binary 1
 #define GL_MALI_PROGRAM_BINARY_ARM        0x8F61
@@ -691,17 +1013,83 @@
 #define GL_ARM_shader_framebuffer_fetch_depth_stencil 1
 #endif /* GL_ARM_shader_framebuffer_fetch_depth_stencil */
 
+#ifndef GL_DMP_program_binary
+#define GL_DMP_program_binary 1
+#define GL_SMAPHS30_PROGRAM_BINARY_DMP    0x9251
+#define GL_SMAPHS_PROGRAM_BINARY_DMP      0x9252
+#define GL_DMP_PROGRAM_BINARY_DMP         0x9253
+#endif /* GL_DMP_program_binary */
+
 #ifndef GL_DMP_shader_binary
 #define GL_DMP_shader_binary 1
 #define GL_SHADER_BINARY_DMP              0x9250
 #endif /* GL_DMP_shader_binary */
 
+#ifndef GL_EXT_YUV_target
+#define GL_EXT_YUV_target 1
+#define GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT    0x8BE7
+#endif /* GL_EXT_YUV_target */
+
+#ifndef GL_EXT_base_instance
+#define GL_EXT_base_instance 1
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawArraysInstancedBaseInstanceEXT (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance);
+#endif
+#endif /* GL_EXT_base_instance */
+
+#ifndef GL_EXT_blend_func_extended
+#define GL_EXT_blend_func_extended 1
+#define GL_SRC1_COLOR_EXT                 0x88F9
+#define GL_SRC1_ALPHA_EXT                 0x8589
+#define GL_ONE_MINUS_SRC1_COLOR_EXT       0x88FA
+#define GL_ONE_MINUS_SRC1_ALPHA_EXT       0x88FB
+#define GL_SRC_ALPHA_SATURATE_EXT         0x0308
+#define GL_LOCATION_INDEX_EXT             0x930F
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT 0x88FC
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDEXTPROC) (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATAINDEXEXTPROC) (GLuint program, const GLchar *name);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBindFragDataLocationIndexedEXT (GLuint program, GLuint colorNumber, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocationIndexEXT (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL GLint GL_APIENTRY glGetFragDataIndexEXT (GLuint program, const GLchar *name);
+#endif
+#endif /* GL_EXT_blend_func_extended */
+
 #ifndef GL_EXT_blend_minmax
 #define GL_EXT_blend_minmax 1
 #define GL_MIN_EXT                        0x8007
 #define GL_MAX_EXT                        0x8008
 #endif /* GL_EXT_blend_minmax */
 
+#ifndef GL_EXT_buffer_storage
+#define GL_EXT_buffer_storage 1
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_PERSISTENT_BIT_EXT         0x0040
+#define GL_MAP_COHERENT_BIT_EXT           0x0080
+#define GL_DYNAMIC_STORAGE_BIT_EXT        0x0100
+#define GL_CLIENT_STORAGE_BIT_EXT         0x0200
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
+#define GL_BUFFER_IMMUTABLE_STORAGE_EXT   0x821F
+#define GL_BUFFER_STORAGE_FLAGS_EXT       0x8220
+typedef void (GL_APIENTRYP PFNGLBUFFERSTORAGEEXTPROC) (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBufferStorageEXT (GLenum target, GLsizeiptr size, const void *data, GLbitfield flags);
+#endif
+#endif /* GL_EXT_buffer_storage */
+
+#ifndef GL_EXT_color_buffer_float
+#define GL_EXT_color_buffer_float 1
+#endif /* GL_EXT_color_buffer_float */
+
 #ifndef GL_EXT_color_buffer_half_float
 #define GL_EXT_color_buffer_half_float 1
 #define GL_RGBA16F_EXT                    0x881A
@@ -839,8 +1227,6 @@
 
 #ifndef GL_EXT_draw_buffers_indexed
 #define GL_EXT_draw_buffers_indexed 1
-#define GL_MIN                            0x8007
-#define GL_MAX                            0x8008
 typedef void (GL_APIENTRYP PFNGLENABLEIEXTPROC) (GLenum target, GLuint index);
 typedef void (GL_APIENTRYP PFNGLDISABLEIEXTPROC) (GLenum target, GLuint index);
 typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode);
@@ -861,6 +1247,20 @@
 #endif
 #endif /* GL_EXT_draw_buffers_indexed */
 
+#ifndef GL_EXT_draw_elements_base_vertex
+#define GL_EXT_draw_elements_base_vertex 1
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
+#endif
+#endif /* GL_EXT_draw_elements_base_vertex */
+
 #ifndef GL_EXT_draw_instanced
 #define GL_EXT_draw_instanced 1
 typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount);
@@ -871,6 +1271,14 @@
 #endif
 #endif /* GL_EXT_draw_instanced */
 
+#ifndef GL_EXT_float_blend
+#define GL_EXT_float_blend 1
+#endif /* GL_EXT_float_blend */
+
+#ifndef GL_EXT_geometry_point_size
+#define GL_EXT_geometry_point_size 1
+#endif /* GL_EXT_geometry_point_size */
+
 #ifndef GL_EXT_geometry_shader
 #define GL_EXT_geometry_shader 1
 #define GL_GEOMETRY_SHADER_EXT            0x8DD9
@@ -951,6 +1359,22 @@
 #endif
 #endif /* GL_EXT_multi_draw_arrays */
 
+#ifndef GL_EXT_multi_draw_indirect
+#define GL_EXT_multi_draw_indirect 1
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glMultiDrawArraysIndirectEXT (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
+GL_APICALL void GL_APIENTRY glMultiDrawElementsIndirectEXT (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
+#endif
+#endif /* GL_EXT_multi_draw_indirect */
+
+#ifndef GL_EXT_multisampled_compatibility
+#define GL_EXT_multisampled_compatibility 1
+#define GL_MULTISAMPLE_EXT                0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT        0x809F
+#endif /* GL_EXT_multisampled_compatibility */
+
 #ifndef GL_EXT_multisampled_render_to_texture
 #define GL_EXT_multisampled_render_to_texture 1
 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C
@@ -988,6 +1412,10 @@
 #define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A
 #endif /* GL_EXT_occlusion_query_boolean */
 
+#ifndef GL_EXT_post_depth_coverage
+#define GL_EXT_post_depth_coverage 1
+#endif /* GL_EXT_post_depth_coverage */
+
 #ifndef GL_EXT_primitive_bounding_box
 #define GL_EXT_primitive_bounding_box 1
 #define GL_PRIMITIVE_BOUNDING_BOX_EXT     0x92BE
@@ -1007,12 +1435,36 @@
 #define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1
 #endif /* GL_EXT_pvrtc_sRGB */
 
+#ifndef GL_EXT_raster_multisample
+#define GL_EXT_raster_multisample 1
+#define GL_RASTER_MULTISAMPLE_EXT         0x9327
+#define GL_RASTER_SAMPLES_EXT             0x9328
+#define GL_MAX_RASTER_SAMPLES_EXT         0x9329
+#define GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT 0x932A
+#define GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT 0x932B
+#define GL_EFFECTIVE_RASTER_SAMPLES_EXT   0x932C
+typedef void (GL_APIENTRYP PFNGLRASTERSAMPLESEXTPROC) (GLuint samples, GLboolean fixedsamplelocations);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glRasterSamplesEXT (GLuint samples, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_EXT_raster_multisample */
+
 #ifndef GL_EXT_read_format_bgra
 #define GL_EXT_read_format_bgra 1
 #define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365
 #define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366
 #endif /* GL_EXT_read_format_bgra */
 
+#ifndef GL_EXT_render_snorm
+#define GL_EXT_render_snorm 1
+#define GL_R8_SNORM                       0x8F94
+#define GL_RG8_SNORM                      0x8F95
+#define GL_RGBA8_SNORM                    0x8F97
+#define GL_R16_SNORM_EXT                  0x8F98
+#define GL_RG16_SNORM_EXT                 0x8F99
+#define GL_RGBA16_SNORM_EXT               0x8F9B
+#endif /* GL_EXT_render_snorm */
+
 #ifndef GL_EXT_robustness
 #define GL_EXT_robustness 1
 #define GL_GUILTY_CONTEXT_RESET_EXT       0x8253
@@ -1183,6 +1635,31 @@
 #define GL_SAMPLER_2D_SHADOW_EXT          0x8B62
 #endif /* GL_EXT_shadow_samplers */
 
+#ifndef GL_EXT_sparse_texture
+#define GL_EXT_sparse_texture 1
+#define GL_TEXTURE_SPARSE_EXT             0x91A6
+#define GL_VIRTUAL_PAGE_SIZE_INDEX_EXT    0x91A7
+#define GL_NUM_SPARSE_LEVELS_EXT          0x91AA
+#define GL_NUM_VIRTUAL_PAGE_SIZES_EXT     0x91A8
+#define GL_VIRTUAL_PAGE_SIZE_X_EXT        0x9195
+#define GL_VIRTUAL_PAGE_SIZE_Y_EXT        0x9196
+#define GL_VIRTUAL_PAGE_SIZE_Z_EXT        0x9197
+#define GL_TEXTURE_2D_ARRAY               0x8C1A
+#define GL_TEXTURE_3D                     0x806F
+#define GL_MAX_SPARSE_TEXTURE_SIZE_EXT    0x9198
+#define GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT 0x9199
+#define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT 0x919A
+#define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT 0x91A9
+typedef void (GL_APIENTRYP PFNGLTEXPAGECOMMITMENTEXTPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glTexPageCommitmentEXT (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit);
+#endif
+#endif /* GL_EXT_sparse_texture */
+
+#ifndef GL_EXT_tessellation_point_size
+#define GL_EXT_tessellation_point_size 1
+#endif /* GL_EXT_tessellation_point_size */
+
 #ifndef GL_EXT_tessellation_shader
 #define GL_EXT_tessellation_shader 1
 #define GL_PATCHES_EXT                    0x000E
@@ -1313,10 +1790,23 @@
 #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF
 #endif /* GL_EXT_texture_filter_anisotropic */
 
+#ifndef GL_EXT_texture_filter_minmax
+#define GL_EXT_texture_filter_minmax 1
+#endif /* GL_EXT_texture_filter_minmax */
+
 #ifndef GL_EXT_texture_format_BGRA8888
 #define GL_EXT_texture_format_BGRA8888 1
 #endif /* GL_EXT_texture_format_BGRA8888 */
 
+#ifndef GL_EXT_texture_norm16
+#define GL_EXT_texture_norm16 1
+#define GL_R16_EXT                        0x822A
+#define GL_RG16_EXT                       0x822C
+#define GL_RGBA16_EXT                     0x805B
+#define GL_RGB16_EXT                      0x8054
+#define GL_RGB16_SNORM_EXT                0x8F9A
+#endif /* GL_EXT_texture_norm16 */
+
 #ifndef GL_EXT_texture_rg
 #define GL_EXT_texture_rg 1
 #define GL_RED_EXT                        0x1903
@@ -1325,6 +1815,16 @@
 #define GL_RG8_EXT                        0x822B
 #endif /* GL_EXT_texture_rg */
 
+#ifndef GL_EXT_texture_sRGB_R8
+#define GL_EXT_texture_sRGB_R8 1
+#define GL_SR8_EXT                        0x8FBD
+#endif /* GL_EXT_texture_sRGB_R8 */
+
+#ifndef GL_EXT_texture_sRGB_RG8
+#define GL_EXT_texture_sRGB_RG8 1
+#define GL_SRG8_EXT                       0x8FBE
+#endif /* GL_EXT_texture_sRGB_RG8 */
+
 #ifndef GL_EXT_texture_sRGB_decode
 #define GL_EXT_texture_sRGB_decode 1
 #define GL_TEXTURE_SRGB_DECODE_EXT        0x8A48
@@ -1375,7 +1875,6 @@
 #define GL_TEXTURE_VIEW_NUM_LEVELS_EXT    0x82DC
 #define GL_TEXTURE_VIEW_MIN_LAYER_EXT     0x82DD
 #define GL_TEXTURE_VIEW_NUM_LAYERS_EXT    0x82DE
-#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
 typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
 #ifdef GL_GLEXT_PROTOTYPES
 GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
@@ -1438,6 +1937,21 @@
 #define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138
 #endif /* GL_IMG_texture_compression_pvrtc2 */
 
+#ifndef GL_IMG_texture_filter_cubic
+#define GL_IMG_texture_filter_cubic 1
+#define GL_CUBIC_IMG                      0x9139
+#define GL_CUBIC_MIPMAP_NEAREST_IMG       0x913A
+#define GL_CUBIC_MIPMAP_LINEAR_IMG        0x913B
+#endif /* GL_IMG_texture_filter_cubic */
+
+#ifndef GL_INTEL_framebuffer_CMAA
+#define GL_INTEL_framebuffer_CMAA 1
+typedef void (GL_APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void);
+#endif
+#endif /* GL_INTEL_framebuffer_CMAA */
+
 #ifndef GL_INTEL_performance_query
 #define GL_INTEL_performance_query 1
 #define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000
@@ -1484,6 +1998,38 @@
 #endif
 #endif /* GL_INTEL_performance_query */
 
+#ifndef GL_NV_bindless_texture
+#define GL_NV_bindless_texture 1
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef GLuint64 (GL_APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access);
+typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle);
+typedef GLboolean (GL_APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleNV (GLuint texture);
+GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle);
+GL_APICALL GLuint64 GL_APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format);
+GL_APICALL void GL_APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access);
+GL_APICALL void GL_APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle);
+GL_APICALL void GL_APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value);
+GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values);
+GL_APICALL GLboolean GL_APIENTRY glIsTextureHandleResidentNV (GLuint64 handle);
+GL_APICALL GLboolean GL_APIENTRY glIsImageHandleResidentNV (GLuint64 handle);
+#endif
+#endif /* GL_NV_bindless_texture */
+
 #ifndef GL_NV_blend_equation_advanced
 #define GL_NV_blend_equation_advanced 1
 #define GL_BLEND_OVERLAP_NV               0x9281
@@ -1548,6 +2094,32 @@
 #define GL_BLEND_ADVANCED_COHERENT_NV     0x9285
 #endif /* GL_NV_blend_equation_advanced_coherent */
 
+#ifndef GL_NV_conditional_render
+#define GL_NV_conditional_render 1
+#define GL_QUERY_WAIT_NV                  0x8E13
+#define GL_QUERY_NO_WAIT_NV               0x8E14
+#define GL_QUERY_BY_REGION_WAIT_NV        0x8E15
+#define GL_QUERY_BY_REGION_NO_WAIT_NV     0x8E16
+typedef void (GL_APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode);
+GL_APICALL void GL_APIENTRY glEndConditionalRenderNV (void);
+#endif
+#endif /* GL_NV_conditional_render */
+
+#ifndef GL_NV_conservative_raster
+#define GL_NV_conservative_raster 1
+#define GL_CONSERVATIVE_RASTERIZATION_NV  0x9346
+#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347
+#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348
+#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349
+typedef void (GL_APIENTRYP PFNGLSUBPIXELPRECISIONBIASNVPROC) (GLuint xbits, GLuint ybits);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits);
+#endif
+#endif /* GL_NV_conservative_raster */
+
 #ifndef GL_NV_copy_buffer
 #define GL_NV_copy_buffer 1
 #define GL_COPY_READ_BUFFER_NV            0x8F36
@@ -1665,6 +2237,25 @@
 #endif
 #endif /* GL_NV_fence */
 
+#ifndef GL_NV_fill_rectangle
+#define GL_NV_fill_rectangle 1
+#define GL_FILL_RECTANGLE_NV              0x933C
+#endif /* GL_NV_fill_rectangle */
+
+#ifndef GL_NV_fragment_coverage_to_color
+#define GL_NV_fragment_coverage_to_color 1
+#define GL_FRAGMENT_COVERAGE_TO_COLOR_NV  0x92DD
+#define GL_FRAGMENT_COVERAGE_COLOR_NV     0x92DE
+typedef void (GL_APIENTRYP PFNGLFRAGMENTCOVERAGECOLORNVPROC) (GLuint color);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFragmentCoverageColorNV (GLuint color);
+#endif
+#endif /* GL_NV_fragment_coverage_to_color */
+
+#ifndef GL_NV_fragment_shader_interlock
+#define GL_NV_fragment_shader_interlock 1
+#endif /* GL_NV_fragment_shader_interlock */
+
 #ifndef GL_NV_framebuffer_blit
 #define GL_NV_framebuffer_blit 1
 #define GL_READ_FRAMEBUFFER_NV            0x8CA8
@@ -1677,6 +2268,26 @@
 #endif
 #endif /* GL_NV_framebuffer_blit */
 
+#ifndef GL_NV_framebuffer_mixed_samples
+#define GL_NV_framebuffer_mixed_samples 1
+#define GL_COVERAGE_MODULATION_TABLE_NV   0x9331
+#define GL_COLOR_SAMPLES_NV               0x8E20
+#define GL_DEPTH_SAMPLES_NV               0x932D
+#define GL_STENCIL_SAMPLES_NV             0x932E
+#define GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV 0x932F
+#define GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV 0x9330
+#define GL_COVERAGE_MODULATION_NV         0x9332
+#define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v);
+GL_APICALL void GL_APIENTRY glCoverageModulationNV (GLenum components);
+#endif
+#endif /* GL_NV_framebuffer_mixed_samples */
+
 #ifndef GL_NV_framebuffer_multisample
 #define GL_NV_framebuffer_multisample 1
 #define GL_RENDERBUFFER_SAMPLES_NV        0x8CAB
@@ -1692,6 +2303,14 @@
 #define GL_NV_generate_mipmap_sRGB 1
 #endif /* GL_NV_generate_mipmap_sRGB */
 
+#ifndef GL_NV_geometry_shader_passthrough
+#define GL_NV_geometry_shader_passthrough 1
+#endif /* GL_NV_geometry_shader_passthrough */
+
+#ifndef GL_NV_image_formats
+#define GL_NV_image_formats 1
+#endif /* GL_NV_image_formats */
+
 #ifndef GL_NV_instanced_arrays
 #define GL_NV_instanced_arrays 1
 #define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE
@@ -1701,6 +2320,20 @@
 #endif
 #endif /* GL_NV_instanced_arrays */
 
+#ifndef GL_NV_internalformat_sample_query
+#define GL_NV_internalformat_sample_query 1
+#define GL_TEXTURE_2D_MULTISAMPLE         0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY   0x9102
+#define GL_MULTISAMPLES_NV                0x9371
+#define GL_SUPERSAMPLE_SCALE_X_NV         0x9372
+#define GL_SUPERSAMPLE_SCALE_Y_NV         0x9373
+#define GL_CONFORMANT_NV                  0x9374
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_NV_internalformat_sample_query */
+
 #ifndef GL_NV_non_square_matrices
 #define GL_NV_non_square_matrices 1
 #define GL_FLOAT_MAT2x3_NV                0x8B65
@@ -1725,6 +2358,298 @@
 #endif
 #endif /* GL_NV_non_square_matrices */
 
+#ifndef GL_NV_path_rendering
+#define GL_NV_path_rendering 1
+#define GL_PATH_FORMAT_SVG_NV             0x9070
+#define GL_PATH_FORMAT_PS_NV              0x9071
+#define GL_STANDARD_FONT_NAME_NV          0x9072
+#define GL_SYSTEM_FONT_NAME_NV            0x9073
+#define GL_FILE_NAME_NV                   0x9074
+#define GL_PATH_STROKE_WIDTH_NV           0x9075
+#define GL_PATH_END_CAPS_NV               0x9076
+#define GL_PATH_INITIAL_END_CAP_NV        0x9077
+#define GL_PATH_TERMINAL_END_CAP_NV       0x9078
+#define GL_PATH_JOIN_STYLE_NV             0x9079
+#define GL_PATH_MITER_LIMIT_NV            0x907A
+#define GL_PATH_DASH_CAPS_NV              0x907B
+#define GL_PATH_INITIAL_DASH_CAP_NV       0x907C
+#define GL_PATH_TERMINAL_DASH_CAP_NV      0x907D
+#define GL_PATH_DASH_OFFSET_NV            0x907E
+#define GL_PATH_CLIENT_LENGTH_NV          0x907F
+#define GL_PATH_FILL_MODE_NV              0x9080
+#define GL_PATH_FILL_MASK_NV              0x9081
+#define GL_PATH_FILL_COVER_MODE_NV        0x9082
+#define GL_PATH_STROKE_COVER_MODE_NV      0x9083
+#define GL_PATH_STROKE_MASK_NV            0x9084
+#define GL_COUNT_UP_NV                    0x9088
+#define GL_COUNT_DOWN_NV                  0x9089
+#define GL_PATH_OBJECT_BOUNDING_BOX_NV    0x908A
+#define GL_CONVEX_HULL_NV                 0x908B
+#define GL_BOUNDING_BOX_NV                0x908D
+#define GL_TRANSLATE_X_NV                 0x908E
+#define GL_TRANSLATE_Y_NV                 0x908F
+#define GL_TRANSLATE_2D_NV                0x9090
+#define GL_TRANSLATE_3D_NV                0x9091
+#define GL_AFFINE_2D_NV                   0x9092
+#define GL_AFFINE_3D_NV                   0x9094
+#define GL_TRANSPOSE_AFFINE_2D_NV         0x9096
+#define GL_TRANSPOSE_AFFINE_3D_NV         0x9098
+#define GL_UTF8_NV                        0x909A
+#define GL_UTF16_NV                       0x909B
+#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C
+#define GL_PATH_COMMAND_COUNT_NV          0x909D
+#define GL_PATH_COORD_COUNT_NV            0x909E
+#define GL_PATH_DASH_ARRAY_COUNT_NV       0x909F
+#define GL_PATH_COMPUTED_LENGTH_NV        0x90A0
+#define GL_PATH_FILL_BOUNDING_BOX_NV      0x90A1
+#define GL_PATH_STROKE_BOUNDING_BOX_NV    0x90A2
+#define GL_SQUARE_NV                      0x90A3
+#define GL_ROUND_NV                       0x90A4
+#define GL_TRIANGULAR_NV                  0x90A5
+#define GL_BEVEL_NV                       0x90A6
+#define GL_MITER_REVERT_NV                0x90A7
+#define GL_MITER_TRUNCATE_NV              0x90A8
+#define GL_SKIP_MISSING_GLYPH_NV          0x90A9
+#define GL_USE_MISSING_GLYPH_NV           0x90AA
+#define GL_PATH_ERROR_POSITION_NV         0x90AB
+#define GL_ACCUM_ADJACENT_PAIRS_NV        0x90AD
+#define GL_ADJACENT_PAIRS_NV              0x90AE
+#define GL_FIRST_TO_REST_NV               0x90AF
+#define GL_PATH_GEN_MODE_NV               0x90B0
+#define GL_PATH_GEN_COEFF_NV              0x90B1
+#define GL_PATH_GEN_COMPONENTS_NV         0x90B3
+#define GL_PATH_STENCIL_FUNC_NV           0x90B7
+#define GL_PATH_STENCIL_REF_NV            0x90B8
+#define GL_PATH_STENCIL_VALUE_MASK_NV     0x90B9
+#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD
+#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE
+#define GL_PATH_COVER_DEPTH_FUNC_NV       0x90BF
+#define GL_PATH_DASH_OFFSET_RESET_NV      0x90B4
+#define GL_MOVE_TO_RESETS_NV              0x90B5
+#define GL_MOVE_TO_CONTINUES_NV           0x90B6
+#define GL_CLOSE_PATH_NV                  0x00
+#define GL_MOVE_TO_NV                     0x02
+#define GL_RELATIVE_MOVE_TO_NV            0x03
+#define GL_LINE_TO_NV                     0x04
+#define GL_RELATIVE_LINE_TO_NV            0x05
+#define GL_HORIZONTAL_LINE_TO_NV          0x06
+#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07
+#define GL_VERTICAL_LINE_TO_NV            0x08
+#define GL_RELATIVE_VERTICAL_LINE_TO_NV   0x09
+#define GL_QUADRATIC_CURVE_TO_NV          0x0A
+#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B
+#define GL_CUBIC_CURVE_TO_NV              0x0C
+#define GL_RELATIVE_CUBIC_CURVE_TO_NV     0x0D
+#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV   0x0E
+#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F
+#define GL_SMOOTH_CUBIC_CURVE_TO_NV       0x10
+#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11
+#define GL_SMALL_CCW_ARC_TO_NV            0x12
+#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV   0x13
+#define GL_SMALL_CW_ARC_TO_NV             0x14
+#define GL_RELATIVE_SMALL_CW_ARC_TO_NV    0x15
+#define GL_LARGE_CCW_ARC_TO_NV            0x16
+#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV   0x17
+#define GL_LARGE_CW_ARC_TO_NV             0x18
+#define GL_RELATIVE_LARGE_CW_ARC_TO_NV    0x19
+#define GL_RESTART_PATH_NV                0xF0
+#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV    0xF2
+#define GL_DUP_LAST_CUBIC_CURVE_TO_NV     0xF4
+#define GL_RECT_NV                        0xF6
+#define GL_CIRCULAR_CCW_ARC_TO_NV         0xF8
+#define GL_CIRCULAR_CW_ARC_TO_NV          0xFA
+#define GL_CIRCULAR_TANGENT_ARC_TO_NV     0xFC
+#define GL_ARC_TO_NV                      0xFE
+#define GL_RELATIVE_ARC_TO_NV             0xFF
+#define GL_BOLD_BIT_NV                    0x01
+#define GL_ITALIC_BIT_NV                  0x02
+#define GL_GLYPH_WIDTH_BIT_NV             0x01
+#define GL_GLYPH_HEIGHT_BIT_NV            0x02
+#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04
+#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08
+#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10
+#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20
+#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40
+#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80
+#define GL_GLYPH_HAS_KERNING_BIT_NV       0x100
+#define GL_FONT_X_MIN_BOUNDS_BIT_NV       0x00010000
+#define GL_FONT_Y_MIN_BOUNDS_BIT_NV       0x00020000
+#define GL_FONT_X_MAX_BOUNDS_BIT_NV       0x00040000
+#define GL_FONT_Y_MAX_BOUNDS_BIT_NV       0x00080000
+#define GL_FONT_UNITS_PER_EM_BIT_NV       0x00100000
+#define GL_FONT_ASCENDER_BIT_NV           0x00200000
+#define GL_FONT_DESCENDER_BIT_NV          0x00400000
+#define GL_FONT_HEIGHT_BIT_NV             0x00800000
+#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV  0x01000000
+#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000
+#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000
+#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000
+#define GL_FONT_HAS_KERNING_BIT_NV        0x10000000
+#define GL_ROUNDED_RECT_NV                0xE8
+#define GL_RELATIVE_ROUNDED_RECT_NV       0xE9
+#define GL_ROUNDED_RECT2_NV               0xEA
+#define GL_RELATIVE_ROUNDED_RECT2_NV      0xEB
+#define GL_ROUNDED_RECT4_NV               0xEC
+#define GL_RELATIVE_ROUNDED_RECT4_NV      0xED
+#define GL_ROUNDED_RECT8_NV               0xEE
+#define GL_RELATIVE_ROUNDED_RECT8_NV      0xEF
+#define GL_RELATIVE_RECT_NV               0xF7
+#define GL_FONT_GLYPHS_AVAILABLE_NV       0x9368
+#define GL_FONT_TARGET_UNAVAILABLE_NV     0x9369
+#define GL_FONT_UNAVAILABLE_NV            0x936A
+#define GL_FONT_UNINTELLIGIBLE_NV         0x936B
+#define GL_CONIC_CURVE_TO_NV              0x1A
+#define GL_RELATIVE_CONIC_CURVE_TO_NV     0x1B
+#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV  0x20000000
+#define GL_STANDARD_FONT_FORMAT_NV        0x936C
+#define GL_PATH_PROJECTION_NV             0x1701
+#define GL_PATH_MODELVIEW_NV              0x1700
+#define GL_PATH_MODELVIEW_STACK_DEPTH_NV  0x0BA3
+#define GL_PATH_MODELVIEW_MATRIX_NV       0x0BA6
+#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36
+#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3
+#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4
+#define GL_PATH_PROJECTION_MATRIX_NV      0x0BA7
+#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38
+#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4
+#define GL_FRAGMENT_INPUT_NV              0x936D
+typedef GLuint (GL_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range);
+typedef void (GL_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range);
+typedef GLboolean (GL_APIENTRYP PFNGLISPATHNVPROC) (GLuint path);
+typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+typedef void (GL_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+typedef void (GL_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath);
+typedef void (GL_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands);
+typedef void (GL_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords);
+typedef void (GL_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+typedef void (GL_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y);
+typedef GLfloat (GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments);
+typedef GLboolean (GL_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range);
+GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range);
+GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path);
+GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords);
+GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString);
+GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights);
+GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath);
+GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight);
+GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value);
+GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value);
+GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func);
+GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value);
+GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value);
+GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands);
+GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords);
+GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray);
+GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics);
+GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y);
+GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y);
+GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments);
+GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode);
+GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]);
+GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale);
+GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs);
+GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params);
+#endif
+#endif /* GL_NV_path_rendering */
+
+#ifndef GL_NV_path_rendering_shared_edge
+#define GL_NV_path_rendering_shared_edge 1
+#define GL_SHARED_EDGE_NV                 0xC0
+#endif /* GL_NV_path_rendering_shared_edge */
+
+#ifndef GL_NV_polygon_mode
+#define GL_NV_polygon_mode 1
+#define GL_POLYGON_MODE_NV                0x0B40
+#define GL_POLYGON_OFFSET_POINT_NV        0x2A01
+#define GL_POLYGON_OFFSET_LINE_NV         0x2A02
+#define GL_POINT_NV                       0x1B00
+#define GL_LINE_NV                        0x1B01
+#define GL_FILL_NV                        0x1B02
+typedef void (GL_APIENTRYP PFNGLPOLYGONMODENVPROC) (GLenum face, GLenum mode);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glPolygonModeNV (GLenum face, GLenum mode);
+#endif
+#endif /* GL_NV_polygon_mode */
+
 #ifndef GL_NV_read_buffer
 #define GL_NV_read_buffer 1
 #define GL_READ_BUFFER_NV                 0x0C02
@@ -1764,6 +2689,34 @@
 #define GL_ETC1_SRGB8_NV                  0x88EE
 #endif /* GL_NV_sRGB_formats */
 
+#ifndef GL_NV_sample_locations
+#define GL_NV_sample_locations 1
+#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV 0x933E
+#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV 0x933F
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV 0x9340
+#define GL_SAMPLE_LOCATION_NV             0x8E50
+#define GL_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9341
+#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV 0x9342
+#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV 0x9343
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLRESOLVEDEPTHVALUESNVPROC) (void);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferSampleLocationsfvNV (GLenum target, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glNamedFramebufferSampleLocationsfvNV (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glResolveDepthValuesNV (void);
+#endif
+#endif /* GL_NV_sample_locations */
+
+#ifndef GL_NV_sample_mask_override_coverage
+#define GL_NV_sample_mask_override_coverage 1
+#endif /* GL_NV_sample_mask_override_coverage */
+
+#ifndef GL_NV_shader_noperspective_interpolation
+#define GL_NV_shader_noperspective_interpolation 1
+#endif /* GL_NV_shader_noperspective_interpolation */
+
 #ifndef GL_NV_shadow_samplers_array
 #define GL_NV_shadow_samplers_array 1
 #define GL_SAMPLER_2D_ARRAY_SHADOW_NV     0x8DC4
@@ -1788,6 +2741,67 @@
 #define GL_NV_texture_npot_2D_mipmap 1
 #endif /* GL_NV_texture_npot_2D_mipmap */
 
+#ifndef GL_NV_viewport_array
+#define GL_NV_viewport_array 1
+#define GL_MAX_VIEWPORTS_NV               0x825B
+#define GL_VIEWPORT_SUBPIXEL_BITS_NV      0x825C
+#define GL_VIEWPORT_BOUNDS_RANGE_NV       0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F
+typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVNVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDNVPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVNVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVNVPROC) (GLuint first, GLsizei count, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFNVPROC) (GLuint index, GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLGETFLOATI_VNVPROC) (GLenum target, GLuint index, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLENABLEINVPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEINVPROC) (GLenum target, GLuint index);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDINVPROC) (GLenum target, GLuint index);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glViewportArrayvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glViewportIndexedfNV (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h);
+GL_APICALL void GL_APIENTRY glViewportIndexedfvNV (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glScissorArrayvNV (GLuint first, GLsizei count, const GLint *v);
+GL_APICALL void GL_APIENTRY glScissorIndexedNV (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glScissorIndexedvNV (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glDepthRangeArrayfvNV (GLuint first, GLsizei count, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glDepthRangeIndexedfNV (GLuint index, GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glGetFloati_vNV (GLenum target, GLuint index, GLfloat *data);
+GL_APICALL void GL_APIENTRY glEnableiNV (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisableiNV (GLenum target, GLuint index);
+GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index);
+#endif
+#endif /* GL_NV_viewport_array */
+
+#ifndef GL_NV_viewport_array2
+#define GL_NV_viewport_array2 1
+#endif /* GL_NV_viewport_array2 */
+
+#ifndef GL_OVR_multiview
+#define GL_OVR_multiview 1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632
+#define GL_MAX_VIEWS_OVR                  0x9631
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview */
+
+#ifndef GL_OVR_multiview2
+#define GL_OVR_multiview2 1
+#endif /* GL_OVR_multiview2 */
+
+#ifndef GL_OVR_multiview_multisampled_render_to_texture
+#define GL_OVR_multiview_multisampled_render_to_texture 1
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#ifdef GL_GLEXT_PROTOTYPES
+GL_APICALL void GL_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+#endif
+#endif /* GL_OVR_multiview_multisampled_render_to_texture */
+
 #ifndef GL_QCOM_alpha_test
 #define GL_QCOM_alpha_test 1
 #define GL_ALPHA_TEST_QCOM                0x0BC0
diff --git a/opengl/include/GLES3/gl3.h b/opengl/include/GLES3/gl3.h
index c9a3175..d51d2e6 100644
--- a/opengl/include/GLES3/gl3.h
+++ b/opengl/include/GLES3/gl3.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -33,17 +33,25 @@
 ** used to make the header, and the header can be found at
 **   http://www.opengl.org/registry/
 **
-** Khronos $Revision: 26696 $ on $Date: 2014-05-17 14:48:55 -0700 (Sat, 17 May 2014) $
+** Khronos $Revision: 32120 $ on $Date: 2015-10-15 04:27:13 -0700 (Thu, 15 Oct 2015) $
 */
 
 #include <GLES3/gl3platform.h>
 
-/* Generated on date 20140517 */
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
 
 /* Generated C header for:
  * API: gles2
  * Profile: common
- * Versions considered: 2\.[0-9]|3.0
+ * Versions considered: 2\.[0-9]|3\.0
  * Versions emitted: .*
  * Default extensions included: None
  * Additional extensions included: _nomatch_^
@@ -374,6 +382,149 @@
 #define GL_RENDERBUFFER_BINDING           0x8CA7
 #define GL_MAX_RENDERBUFFER_SIZE          0x84E8
 #define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
 GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
 GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
 GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -516,6 +667,7 @@
 GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
 GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
 GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
 #endif /* GL_ES_VERSION_2_0 */
 
 #ifndef GL_ES_VERSION_3_0
@@ -705,6 +857,22 @@
 #define GL_COLOR_ATTACHMENT13             0x8CED
 #define GL_COLOR_ATTACHMENT14             0x8CEE
 #define GL_COLOR_ATTACHMENT15             0x8CEF
+#define GL_COLOR_ATTACHMENT16             0x8CF0
+#define GL_COLOR_ATTACHMENT17             0x8CF1
+#define GL_COLOR_ATTACHMENT18             0x8CF2
+#define GL_COLOR_ATTACHMENT19             0x8CF3
+#define GL_COLOR_ATTACHMENT20             0x8CF4
+#define GL_COLOR_ATTACHMENT21             0x8CF5
+#define GL_COLOR_ATTACHMENT22             0x8CF6
+#define GL_COLOR_ATTACHMENT23             0x8CF7
+#define GL_COLOR_ATTACHMENT24             0x8CF8
+#define GL_COLOR_ATTACHMENT25             0x8CF9
+#define GL_COLOR_ATTACHMENT26             0x8CFA
+#define GL_COLOR_ATTACHMENT27             0x8CFB
+#define GL_COLOR_ATTACHMENT28             0x8CFC
+#define GL_COLOR_ATTACHMENT29             0x8CFD
+#define GL_COLOR_ATTACHMENT30             0x8CFE
+#define GL_COLOR_ATTACHMENT31             0x8CFF
 #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
 #define GL_MAX_SAMPLES                    0x8D57
 #define GL_HALF_FLOAT                     0x140B
@@ -826,7 +994,112 @@
 #define GL_MAX_ELEMENT_INDEX              0x8D6B
 #define GL_NUM_SAMPLE_COUNTS              0x9380
 #define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
-GL_APICALL void GL_APIENTRY glReadBuffer (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
 GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
 GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
 GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
@@ -930,6 +1203,7 @@
 GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
 #endif /* GL_ES_VERSION_3_0 */
 
 #ifdef __cplusplus
diff --git a/opengl/include/GLES3/gl31.h b/opengl/include/GLES3/gl31.h
index cfb9069..9b89a0a 100644
--- a/opengl/include/GLES3/gl31.h
+++ b/opengl/include/GLES3/gl31.h
@@ -6,7 +6,7 @@
 #endif
 
 /*
-** Copyright (c) 2013-2014 The Khronos Group Inc.
+** Copyright (c) 2013-2015 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
@@ -38,12 +38,20 @@
 
 #include <GLES3/gl3platform.h>
 
-/* Generated on date 20140517 */
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
 
 /* Generated C header for:
  * API: gles2
  * Profile: common
- * Versions considered: 2.[0-9]|3.[01]
+ * Versions considered: 2\.[0-9]|3\.[01]
  * Versions emitted: .*
  * Default extensions included: None
  * Additional extensions included: _nomatch_^
@@ -374,6 +382,149 @@
 #define GL_RENDERBUFFER_BINDING           0x8CA7
 #define GL_MAX_RENDERBUFFER_SIZE          0x84E8
 #define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
 GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
 GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
 GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
@@ -516,6 +667,7 @@
 GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
 GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
 GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
 #endif /* GL_ES_VERSION_2_0 */
 
 #ifndef GL_ES_VERSION_3_0
@@ -705,6 +857,22 @@
 #define GL_COLOR_ATTACHMENT13             0x8CED
 #define GL_COLOR_ATTACHMENT14             0x8CEE
 #define GL_COLOR_ATTACHMENT15             0x8CEF
+#define GL_COLOR_ATTACHMENT16             0x8CF0
+#define GL_COLOR_ATTACHMENT17             0x8CF1
+#define GL_COLOR_ATTACHMENT18             0x8CF2
+#define GL_COLOR_ATTACHMENT19             0x8CF3
+#define GL_COLOR_ATTACHMENT20             0x8CF4
+#define GL_COLOR_ATTACHMENT21             0x8CF5
+#define GL_COLOR_ATTACHMENT22             0x8CF6
+#define GL_COLOR_ATTACHMENT23             0x8CF7
+#define GL_COLOR_ATTACHMENT24             0x8CF8
+#define GL_COLOR_ATTACHMENT25             0x8CF9
+#define GL_COLOR_ATTACHMENT26             0x8CFA
+#define GL_COLOR_ATTACHMENT27             0x8CFB
+#define GL_COLOR_ATTACHMENT28             0x8CFC
+#define GL_COLOR_ATTACHMENT29             0x8CFD
+#define GL_COLOR_ATTACHMENT30             0x8CFE
+#define GL_COLOR_ATTACHMENT31             0x8CFF
 #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
 #define GL_MAX_SAMPLES                    0x8D57
 #define GL_HALF_FLOAT                     0x140B
@@ -826,7 +994,112 @@
 #define GL_MAX_ELEMENT_INDEX              0x8D6B
 #define GL_NUM_SAMPLE_COUNTS              0x9380
 #define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
-GL_APICALL void GL_APIENTRY glReadBuffer (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
 GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
 GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
 GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
@@ -930,6 +1203,7 @@
 GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
 GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
 GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
 #endif /* GL_ES_VERSION_3_0 */
 
 #ifndef GL_ES_VERSION_3_1
@@ -1107,6 +1381,75 @@
 #define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
 #define GL_MAX_VERTEX_ATTRIB_BINDINGS     0x82DA
 #define GL_MAX_VERTEX_ATTRIB_STRIDE       0x82E5
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+#if GL_GLES_PROTOTYPES
 GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
 GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
 GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
@@ -1175,6 +1518,7 @@
 GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
 GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
 GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+#endif
 #endif /* GL_ES_VERSION_3_1 */
 
 #ifdef __cplusplus
diff --git a/opengl/include/GLES3/gl32.h b/opengl/include/GLES3/gl32.h
new file mode 100644
index 0000000..a2c3611
--- /dev/null
+++ b/opengl/include/GLES3/gl32.h
@@ -0,0 +1,1829 @@
+#ifndef __gl32_h_
+#define __gl32_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2013-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+/*
+** This header is generated from the Khronos OpenGL / OpenGL ES XML
+** API Registry. The current version of the Registry, generator scripts
+** used to make the header, and the header can be found at
+**   http://www.opengl.org/registry/
+**
+** Khronos $Revision$ on $Date$
+*/
+
+#include <GLES3/gl3platform.h>
+
+#ifndef GL_APIENTRYP
+#define GL_APIENTRYP GL_APIENTRY*
+#endif
+
+#if !defined(GL_GLES_PROTOTYPES)
+#define GL_GLES_PROTOTYPES 1
+#endif
+
+/* Generated on date 20151015 */
+
+/* Generated C header for:
+ * API: gles2
+ * Profile: common
+ * Versions considered: 2\.[0-9]|3\.[012]
+ * Versions emitted: .*
+ * Default extensions included: None
+ * Additional extensions included: _nomatch_^
+ * Extensions removed: _nomatch_^
+ */
+
+#ifndef GL_ES_VERSION_2_0
+#define GL_ES_VERSION_2_0 1
+#include <KHR/khrplatform.h>
+typedef khronos_int8_t GLbyte;
+typedef khronos_float_t GLclampf;
+typedef khronos_int32_t GLfixed;
+typedef short GLshort;
+typedef unsigned short GLushort;
+typedef void GLvoid;
+typedef struct __GLsync *GLsync;
+typedef khronos_int64_t GLint64;
+typedef khronos_uint64_t GLuint64;
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef khronos_float_t GLfloat;
+typedef khronos_ssize_t GLsizeiptr;
+typedef khronos_intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef khronos_uint8_t GLubyte;
+#define GL_DEPTH_BUFFER_BIT               0x00000100
+#define GL_STENCIL_BUFFER_BIT             0x00000400
+#define GL_COLOR_BUFFER_BIT               0x00004000
+#define GL_FALSE                          0
+#define GL_TRUE                           1
+#define GL_POINTS                         0x0000
+#define GL_LINES                          0x0001
+#define GL_LINE_LOOP                      0x0002
+#define GL_LINE_STRIP                     0x0003
+#define GL_TRIANGLES                      0x0004
+#define GL_TRIANGLE_STRIP                 0x0005
+#define GL_TRIANGLE_FAN                   0x0006
+#define GL_ZERO                           0
+#define GL_ONE                            1
+#define GL_SRC_COLOR                      0x0300
+#define GL_ONE_MINUS_SRC_COLOR            0x0301
+#define GL_SRC_ALPHA                      0x0302
+#define GL_ONE_MINUS_SRC_ALPHA            0x0303
+#define GL_DST_ALPHA                      0x0304
+#define GL_ONE_MINUS_DST_ALPHA            0x0305
+#define GL_DST_COLOR                      0x0306
+#define GL_ONE_MINUS_DST_COLOR            0x0307
+#define GL_SRC_ALPHA_SATURATE             0x0308
+#define GL_FUNC_ADD                       0x8006
+#define GL_BLEND_EQUATION                 0x8009
+#define GL_BLEND_EQUATION_RGB             0x8009
+#define GL_BLEND_EQUATION_ALPHA           0x883D
+#define GL_FUNC_SUBTRACT                  0x800A
+#define GL_FUNC_REVERSE_SUBTRACT          0x800B
+#define GL_BLEND_DST_RGB                  0x80C8
+#define GL_BLEND_SRC_RGB                  0x80C9
+#define GL_BLEND_DST_ALPHA                0x80CA
+#define GL_BLEND_SRC_ALPHA                0x80CB
+#define GL_CONSTANT_COLOR                 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR       0x8002
+#define GL_CONSTANT_ALPHA                 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA       0x8004
+#define GL_BLEND_COLOR                    0x8005
+#define GL_ARRAY_BUFFER                   0x8892
+#define GL_ELEMENT_ARRAY_BUFFER           0x8893
+#define GL_ARRAY_BUFFER_BINDING           0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING   0x8895
+#define GL_STREAM_DRAW                    0x88E0
+#define GL_STATIC_DRAW                    0x88E4
+#define GL_DYNAMIC_DRAW                   0x88E8
+#define GL_BUFFER_SIZE                    0x8764
+#define GL_BUFFER_USAGE                   0x8765
+#define GL_CURRENT_VERTEX_ATTRIB          0x8626
+#define GL_FRONT                          0x0404
+#define GL_BACK                           0x0405
+#define GL_FRONT_AND_BACK                 0x0408
+#define GL_TEXTURE_2D                     0x0DE1
+#define GL_CULL_FACE                      0x0B44
+#define GL_BLEND                          0x0BE2
+#define GL_DITHER                         0x0BD0
+#define GL_STENCIL_TEST                   0x0B90
+#define GL_DEPTH_TEST                     0x0B71
+#define GL_SCISSOR_TEST                   0x0C11
+#define GL_POLYGON_OFFSET_FILL            0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
+#define GL_SAMPLE_COVERAGE                0x80A0
+#define GL_NO_ERROR                       0
+#define GL_INVALID_ENUM                   0x0500
+#define GL_INVALID_VALUE                  0x0501
+#define GL_INVALID_OPERATION              0x0502
+#define GL_OUT_OF_MEMORY                  0x0505
+#define GL_CW                             0x0900
+#define GL_CCW                            0x0901
+#define GL_LINE_WIDTH                     0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE       0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE       0x846E
+#define GL_CULL_FACE_MODE                 0x0B45
+#define GL_FRONT_FACE                     0x0B46
+#define GL_DEPTH_RANGE                    0x0B70
+#define GL_DEPTH_WRITEMASK                0x0B72
+#define GL_DEPTH_CLEAR_VALUE              0x0B73
+#define GL_DEPTH_FUNC                     0x0B74
+#define GL_STENCIL_CLEAR_VALUE            0x0B91
+#define GL_STENCIL_FUNC                   0x0B92
+#define GL_STENCIL_FAIL                   0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL        0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS        0x0B96
+#define GL_STENCIL_REF                    0x0B97
+#define GL_STENCIL_VALUE_MASK             0x0B93
+#define GL_STENCIL_WRITEMASK              0x0B98
+#define GL_STENCIL_BACK_FUNC              0x8800
+#define GL_STENCIL_BACK_FAIL              0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL   0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS   0x8803
+#define GL_STENCIL_BACK_REF               0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK        0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK         0x8CA5
+#define GL_VIEWPORT                       0x0BA2
+#define GL_SCISSOR_BOX                    0x0C10
+#define GL_COLOR_CLEAR_VALUE              0x0C22
+#define GL_COLOR_WRITEMASK                0x0C23
+#define GL_UNPACK_ALIGNMENT               0x0CF5
+#define GL_PACK_ALIGNMENT                 0x0D05
+#define GL_MAX_TEXTURE_SIZE               0x0D33
+#define GL_MAX_VIEWPORT_DIMS              0x0D3A
+#define GL_SUBPIXEL_BITS                  0x0D50
+#define GL_RED_BITS                       0x0D52
+#define GL_GREEN_BITS                     0x0D53
+#define GL_BLUE_BITS                      0x0D54
+#define GL_ALPHA_BITS                     0x0D55
+#define GL_DEPTH_BITS                     0x0D56
+#define GL_STENCIL_BITS                   0x0D57
+#define GL_POLYGON_OFFSET_UNITS           0x2A00
+#define GL_POLYGON_OFFSET_FACTOR          0x8038
+#define GL_TEXTURE_BINDING_2D             0x8069
+#define GL_SAMPLE_BUFFERS                 0x80A8
+#define GL_SAMPLES                        0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE          0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT         0x80AB
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS     0x86A3
+#define GL_DONT_CARE                      0x1100
+#define GL_FASTEST                        0x1101
+#define GL_NICEST                         0x1102
+#define GL_GENERATE_MIPMAP_HINT           0x8192
+#define GL_BYTE                           0x1400
+#define GL_UNSIGNED_BYTE                  0x1401
+#define GL_SHORT                          0x1402
+#define GL_UNSIGNED_SHORT                 0x1403
+#define GL_INT                            0x1404
+#define GL_UNSIGNED_INT                   0x1405
+#define GL_FLOAT                          0x1406
+#define GL_FIXED                          0x140C
+#define GL_DEPTH_COMPONENT                0x1902
+#define GL_ALPHA                          0x1906
+#define GL_RGB                            0x1907
+#define GL_RGBA                           0x1908
+#define GL_LUMINANCE                      0x1909
+#define GL_LUMINANCE_ALPHA                0x190A
+#define GL_UNSIGNED_SHORT_4_4_4_4         0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1         0x8034
+#define GL_UNSIGNED_SHORT_5_6_5           0x8363
+#define GL_FRAGMENT_SHADER                0x8B30
+#define GL_VERTEX_SHADER                  0x8B31
+#define GL_MAX_VERTEX_ATTRIBS             0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS     0x8DFB
+#define GL_MAX_VARYING_VECTORS            0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS        0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS   0x8DFD
+#define GL_SHADER_TYPE                    0x8B4F
+#define GL_DELETE_STATUS                  0x8B80
+#define GL_LINK_STATUS                    0x8B82
+#define GL_VALIDATE_STATUS                0x8B83
+#define GL_ATTACHED_SHADERS               0x8B85
+#define GL_ACTIVE_UNIFORMS                0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH      0x8B87
+#define GL_ACTIVE_ATTRIBUTES              0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH    0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION       0x8B8C
+#define GL_CURRENT_PROGRAM                0x8B8D
+#define GL_NEVER                          0x0200
+#define GL_LESS                           0x0201
+#define GL_EQUAL                          0x0202
+#define GL_LEQUAL                         0x0203
+#define GL_GREATER                        0x0204
+#define GL_NOTEQUAL                       0x0205
+#define GL_GEQUAL                         0x0206
+#define GL_ALWAYS                         0x0207
+#define GL_KEEP                           0x1E00
+#define GL_REPLACE                        0x1E01
+#define GL_INCR                           0x1E02
+#define GL_DECR                           0x1E03
+#define GL_INVERT                         0x150A
+#define GL_INCR_WRAP                      0x8507
+#define GL_DECR_WRAP                      0x8508
+#define GL_VENDOR                         0x1F00
+#define GL_RENDERER                       0x1F01
+#define GL_VERSION                        0x1F02
+#define GL_EXTENSIONS                     0x1F03
+#define GL_NEAREST                        0x2600
+#define GL_LINEAR                         0x2601
+#define GL_NEAREST_MIPMAP_NEAREST         0x2700
+#define GL_LINEAR_MIPMAP_NEAREST          0x2701
+#define GL_NEAREST_MIPMAP_LINEAR          0x2702
+#define GL_LINEAR_MIPMAP_LINEAR           0x2703
+#define GL_TEXTURE_MAG_FILTER             0x2800
+#define GL_TEXTURE_MIN_FILTER             0x2801
+#define GL_TEXTURE_WRAP_S                 0x2802
+#define GL_TEXTURE_WRAP_T                 0x2803
+#define GL_TEXTURE                        0x1702
+#define GL_TEXTURE_CUBE_MAP               0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP       0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X    0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X    0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y    0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y    0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z    0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z    0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE      0x851C
+#define GL_TEXTURE0                       0x84C0
+#define GL_TEXTURE1                       0x84C1
+#define GL_TEXTURE2                       0x84C2
+#define GL_TEXTURE3                       0x84C3
+#define GL_TEXTURE4                       0x84C4
+#define GL_TEXTURE5                       0x84C5
+#define GL_TEXTURE6                       0x84C6
+#define GL_TEXTURE7                       0x84C7
+#define GL_TEXTURE8                       0x84C8
+#define GL_TEXTURE9                       0x84C9
+#define GL_TEXTURE10                      0x84CA
+#define GL_TEXTURE11                      0x84CB
+#define GL_TEXTURE12                      0x84CC
+#define GL_TEXTURE13                      0x84CD
+#define GL_TEXTURE14                      0x84CE
+#define GL_TEXTURE15                      0x84CF
+#define GL_TEXTURE16                      0x84D0
+#define GL_TEXTURE17                      0x84D1
+#define GL_TEXTURE18                      0x84D2
+#define GL_TEXTURE19                      0x84D3
+#define GL_TEXTURE20                      0x84D4
+#define GL_TEXTURE21                      0x84D5
+#define GL_TEXTURE22                      0x84D6
+#define GL_TEXTURE23                      0x84D7
+#define GL_TEXTURE24                      0x84D8
+#define GL_TEXTURE25                      0x84D9
+#define GL_TEXTURE26                      0x84DA
+#define GL_TEXTURE27                      0x84DB
+#define GL_TEXTURE28                      0x84DC
+#define GL_TEXTURE29                      0x84DD
+#define GL_TEXTURE30                      0x84DE
+#define GL_TEXTURE31                      0x84DF
+#define GL_ACTIVE_TEXTURE                 0x84E0
+#define GL_REPEAT                         0x2901
+#define GL_CLAMP_TO_EDGE                  0x812F
+#define GL_MIRRORED_REPEAT                0x8370
+#define GL_FLOAT_VEC2                     0x8B50
+#define GL_FLOAT_VEC3                     0x8B51
+#define GL_FLOAT_VEC4                     0x8B52
+#define GL_INT_VEC2                       0x8B53
+#define GL_INT_VEC3                       0x8B54
+#define GL_INT_VEC4                       0x8B55
+#define GL_BOOL                           0x8B56
+#define GL_BOOL_VEC2                      0x8B57
+#define GL_BOOL_VEC3                      0x8B58
+#define GL_BOOL_VEC4                      0x8B59
+#define GL_FLOAT_MAT2                     0x8B5A
+#define GL_FLOAT_MAT3                     0x8B5B
+#define GL_FLOAT_MAT4                     0x8B5C
+#define GL_SAMPLER_2D                     0x8B5E
+#define GL_SAMPLER_CUBE                   0x8B60
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED    0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE       0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE     0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE       0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER    0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_COMPILE_STATUS                 0x8B81
+#define GL_INFO_LOG_LENGTH                0x8B84
+#define GL_SHADER_SOURCE_LENGTH           0x8B88
+#define GL_SHADER_COMPILER                0x8DFA
+#define GL_SHADER_BINARY_FORMATS          0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS      0x8DF9
+#define GL_LOW_FLOAT                      0x8DF0
+#define GL_MEDIUM_FLOAT                   0x8DF1
+#define GL_HIGH_FLOAT                     0x8DF2
+#define GL_LOW_INT                        0x8DF3
+#define GL_MEDIUM_INT                     0x8DF4
+#define GL_HIGH_INT                       0x8DF5
+#define GL_FRAMEBUFFER                    0x8D40
+#define GL_RENDERBUFFER                   0x8D41
+#define GL_RGBA4                          0x8056
+#define GL_RGB5_A1                        0x8057
+#define GL_RGB565                         0x8D62
+#define GL_DEPTH_COMPONENT16              0x81A5
+#define GL_STENCIL_INDEX8                 0x8D48
+#define GL_RENDERBUFFER_WIDTH             0x8D42
+#define GL_RENDERBUFFER_HEIGHT            0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT   0x8D44
+#define GL_RENDERBUFFER_RED_SIZE          0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE        0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE         0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE        0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE        0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE      0x8D55
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_COLOR_ATTACHMENT0              0x8CE0
+#define GL_DEPTH_ATTACHMENT               0x8D00
+#define GL_STENCIL_ATTACHMENT             0x8D20
+#define GL_NONE                           0
+#define GL_FRAMEBUFFER_COMPLETE           0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED        0x8CDD
+#define GL_FRAMEBUFFER_BINDING            0x8CA6
+#define GL_RENDERBUFFER_BINDING           0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE          0x84E8
+#define GL_INVALID_FRAMEBUFFER_OPERATION  0x0506
+typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture);
+typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer);
+typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture);
+typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d);
+typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type);
+typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func);
+typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag);
+typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f);
+typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader);
+typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap);
+typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index);
+typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode);
+typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
+typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers);
+typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers);
+typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer);
+typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode);
+typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap);
+typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program);
+typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer);
+typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader);
+typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture);
+typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width);
+typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units);
+typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert);
+typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass);
+typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture);
+GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name);
+GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer);
+GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer);
+GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture);
+GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target);
+GL_APICALL void GL_APIENTRY glClear (GLbitfield mask);
+GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d);
+GL_APICALL void GL_APIENTRY glClearStencil (GLint s);
+GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL GLuint GL_APIENTRY glCreateProgram (void);
+GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type);
+GL_APICALL void GL_APIENTRY glCullFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
+GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader);
+GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures);
+GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func);
+GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag);
+GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f);
+GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader);
+GL_APICALL void GL_APIENTRY glDisable (GLenum cap);
+GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count);
+GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glEnable (GLenum cap);
+GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index);
+GL_APICALL void GL_APIENTRY glFinish (void);
+GL_APICALL void GL_APIENTRY glFlush (void);
+GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode);
+GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
+GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target);
+GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers);
+GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers);
+GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures);
+GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders);
+GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL GLenum GL_APIENTRY glGetError (void);
+GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data);
+GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data);
+GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision);
+GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source);
+GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name);
+GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer);
+GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode);
+GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap);
+GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program);
+GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer);
+GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader);
+GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture);
+GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width);
+GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units);
+GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void);
+GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert);
+GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask);
+GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass);
+GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
+GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params);
+GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUseProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program);
+GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x);
+GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y);
+GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z);
+GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v);
+GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height);
+#endif
+#endif /* GL_ES_VERSION_2_0 */
+
+#ifndef GL_ES_VERSION_3_0
+#define GL_ES_VERSION_3_0 1
+typedef unsigned short GLhalf;
+#define GL_READ_BUFFER                    0x0C02
+#define GL_UNPACK_ROW_LENGTH              0x0CF2
+#define GL_UNPACK_SKIP_ROWS               0x0CF3
+#define GL_UNPACK_SKIP_PIXELS             0x0CF4
+#define GL_PACK_ROW_LENGTH                0x0D02
+#define GL_PACK_SKIP_ROWS                 0x0D03
+#define GL_PACK_SKIP_PIXELS               0x0D04
+#define GL_COLOR                          0x1800
+#define GL_DEPTH                          0x1801
+#define GL_STENCIL                        0x1802
+#define GL_RED                            0x1903
+#define GL_RGB8                           0x8051
+#define GL_RGBA8                          0x8058
+#define GL_RGB10_A2                       0x8059
+#define GL_TEXTURE_BINDING_3D             0x806A
+#define GL_UNPACK_SKIP_IMAGES             0x806D
+#define GL_UNPACK_IMAGE_HEIGHT            0x806E
+#define GL_TEXTURE_3D                     0x806F
+#define GL_TEXTURE_WRAP_R                 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE            0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV    0x8368
+#define GL_MAX_ELEMENTS_VERTICES          0x80E8
+#define GL_MAX_ELEMENTS_INDICES           0x80E9
+#define GL_TEXTURE_MIN_LOD                0x813A
+#define GL_TEXTURE_MAX_LOD                0x813B
+#define GL_TEXTURE_BASE_LEVEL             0x813C
+#define GL_TEXTURE_MAX_LEVEL              0x813D
+#define GL_MIN                            0x8007
+#define GL_MAX                            0x8008
+#define GL_DEPTH_COMPONENT24              0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS           0x84FD
+#define GL_TEXTURE_COMPARE_MODE           0x884C
+#define GL_TEXTURE_COMPARE_FUNC           0x884D
+#define GL_CURRENT_QUERY                  0x8865
+#define GL_QUERY_RESULT                   0x8866
+#define GL_QUERY_RESULT_AVAILABLE         0x8867
+#define GL_BUFFER_MAPPED                  0x88BC
+#define GL_BUFFER_MAP_POINTER             0x88BD
+#define GL_STREAM_READ                    0x88E1
+#define GL_STREAM_COPY                    0x88E2
+#define GL_STATIC_READ                    0x88E5
+#define GL_STATIC_COPY                    0x88E6
+#define GL_DYNAMIC_READ                   0x88E9
+#define GL_DYNAMIC_COPY                   0x88EA
+#define GL_MAX_DRAW_BUFFERS               0x8824
+#define GL_DRAW_BUFFER0                   0x8825
+#define GL_DRAW_BUFFER1                   0x8826
+#define GL_DRAW_BUFFER2                   0x8827
+#define GL_DRAW_BUFFER3                   0x8828
+#define GL_DRAW_BUFFER4                   0x8829
+#define GL_DRAW_BUFFER5                   0x882A
+#define GL_DRAW_BUFFER6                   0x882B
+#define GL_DRAW_BUFFER7                   0x882C
+#define GL_DRAW_BUFFER8                   0x882D
+#define GL_DRAW_BUFFER9                   0x882E
+#define GL_DRAW_BUFFER10                  0x882F
+#define GL_DRAW_BUFFER11                  0x8830
+#define GL_DRAW_BUFFER12                  0x8831
+#define GL_DRAW_BUFFER13                  0x8832
+#define GL_DRAW_BUFFER14                  0x8833
+#define GL_DRAW_BUFFER15                  0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS  0x8B4A
+#define GL_SAMPLER_3D                     0x8B5F
+#define GL_SAMPLER_2D_SHADOW              0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_PIXEL_PACK_BUFFER              0x88EB
+#define GL_PIXEL_UNPACK_BUFFER            0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING      0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING    0x88EF
+#define GL_FLOAT_MAT2x3                   0x8B65
+#define GL_FLOAT_MAT2x4                   0x8B66
+#define GL_FLOAT_MAT3x2                   0x8B67
+#define GL_FLOAT_MAT3x4                   0x8B68
+#define GL_FLOAT_MAT4x2                   0x8B69
+#define GL_FLOAT_MAT4x3                   0x8B6A
+#define GL_SRGB                           0x8C40
+#define GL_SRGB8                          0x8C41
+#define GL_SRGB8_ALPHA8                   0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE         0x884E
+#define GL_MAJOR_VERSION                  0x821B
+#define GL_MINOR_VERSION                  0x821C
+#define GL_NUM_EXTENSIONS                 0x821D
+#define GL_RGBA32F                        0x8814
+#define GL_RGB32F                         0x8815
+#define GL_RGBA16F                        0x881A
+#define GL_RGB16F                         0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER    0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS       0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET       0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET       0x8905
+#define GL_MAX_VARYING_COMPONENTS         0x8B4B
+#define GL_TEXTURE_2D_ARRAY               0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY       0x8C1D
+#define GL_R11F_G11F_B10F                 0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV   0x8C3B
+#define GL_RGB9_E5                        0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV       0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS    0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_RASTERIZER_DISCARD             0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_INTERLEAVED_ATTRIBS            0x8C8C
+#define GL_SEPARATE_ATTRIBS               0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER      0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_RGBA32UI                       0x8D70
+#define GL_RGB32UI                        0x8D71
+#define GL_RGBA16UI                       0x8D76
+#define GL_RGB16UI                        0x8D77
+#define GL_RGBA8UI                        0x8D7C
+#define GL_RGB8UI                         0x8D7D
+#define GL_RGBA32I                        0x8D82
+#define GL_RGB32I                         0x8D83
+#define GL_RGBA16I                        0x8D88
+#define GL_RGB16I                         0x8D89
+#define GL_RGBA8I                         0x8D8E
+#define GL_RGB8I                          0x8D8F
+#define GL_RED_INTEGER                    0x8D94
+#define GL_RGB_INTEGER                    0x8D98
+#define GL_RGBA_INTEGER                   0x8D99
+#define GL_SAMPLER_2D_ARRAY               0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW        0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW            0x8DC5
+#define GL_UNSIGNED_INT_VEC2              0x8DC6
+#define GL_UNSIGNED_INT_VEC3              0x8DC7
+#define GL_UNSIGNED_INT_VEC4              0x8DC8
+#define GL_INT_SAMPLER_2D                 0x8DCA
+#define GL_INT_SAMPLER_3D                 0x8DCB
+#define GL_INT_SAMPLER_CUBE               0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY           0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D        0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D        0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE      0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY  0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS            0x911F
+#define GL_BUFFER_MAP_LENGTH              0x9120
+#define GL_BUFFER_MAP_OFFSET              0x9121
+#define GL_DEPTH_COMPONENT32F             0x8CAC
+#define GL_DEPTH32F_STENCIL8              0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_DEFAULT            0x8218
+#define GL_FRAMEBUFFER_UNDEFINED          0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT       0x821A
+#define GL_DEPTH_STENCIL                  0x84F9
+#define GL_UNSIGNED_INT_24_8              0x84FA
+#define GL_DEPTH24_STENCIL8               0x88F0
+#define GL_UNSIGNED_NORMALIZED            0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING       0x8CA6
+#define GL_READ_FRAMEBUFFER               0x8CA8
+#define GL_DRAW_FRAMEBUFFER               0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING       0x8CAA
+#define GL_RENDERBUFFER_SAMPLES           0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS          0x8CDF
+#define GL_COLOR_ATTACHMENT1              0x8CE1
+#define GL_COLOR_ATTACHMENT2              0x8CE2
+#define GL_COLOR_ATTACHMENT3              0x8CE3
+#define GL_COLOR_ATTACHMENT4              0x8CE4
+#define GL_COLOR_ATTACHMENT5              0x8CE5
+#define GL_COLOR_ATTACHMENT6              0x8CE6
+#define GL_COLOR_ATTACHMENT7              0x8CE7
+#define GL_COLOR_ATTACHMENT8              0x8CE8
+#define GL_COLOR_ATTACHMENT9              0x8CE9
+#define GL_COLOR_ATTACHMENT10             0x8CEA
+#define GL_COLOR_ATTACHMENT11             0x8CEB
+#define GL_COLOR_ATTACHMENT12             0x8CEC
+#define GL_COLOR_ATTACHMENT13             0x8CED
+#define GL_COLOR_ATTACHMENT14             0x8CEE
+#define GL_COLOR_ATTACHMENT15             0x8CEF
+#define GL_COLOR_ATTACHMENT16             0x8CF0
+#define GL_COLOR_ATTACHMENT17             0x8CF1
+#define GL_COLOR_ATTACHMENT18             0x8CF2
+#define GL_COLOR_ATTACHMENT19             0x8CF3
+#define GL_COLOR_ATTACHMENT20             0x8CF4
+#define GL_COLOR_ATTACHMENT21             0x8CF5
+#define GL_COLOR_ATTACHMENT22             0x8CF6
+#define GL_COLOR_ATTACHMENT23             0x8CF7
+#define GL_COLOR_ATTACHMENT24             0x8CF8
+#define GL_COLOR_ATTACHMENT25             0x8CF9
+#define GL_COLOR_ATTACHMENT26             0x8CFA
+#define GL_COLOR_ATTACHMENT27             0x8CFB
+#define GL_COLOR_ATTACHMENT28             0x8CFC
+#define GL_COLOR_ATTACHMENT29             0x8CFD
+#define GL_COLOR_ATTACHMENT30             0x8CFE
+#define GL_COLOR_ATTACHMENT31             0x8CFF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_MAX_SAMPLES                    0x8D57
+#define GL_HALF_FLOAT                     0x140B
+#define GL_MAP_READ_BIT                   0x0001
+#define GL_MAP_WRITE_BIT                  0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT       0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT      0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT         0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT         0x0020
+#define GL_RG                             0x8227
+#define GL_RG_INTEGER                     0x8228
+#define GL_R8                             0x8229
+#define GL_RG8                            0x822B
+#define GL_R16F                           0x822D
+#define GL_R32F                           0x822E
+#define GL_RG16F                          0x822F
+#define GL_RG32F                          0x8230
+#define GL_R8I                            0x8231
+#define GL_R8UI                           0x8232
+#define GL_R16I                           0x8233
+#define GL_R16UI                          0x8234
+#define GL_R32I                           0x8235
+#define GL_R32UI                          0x8236
+#define GL_RG8I                           0x8237
+#define GL_RG8UI                          0x8238
+#define GL_RG16I                          0x8239
+#define GL_RG16UI                         0x823A
+#define GL_RG32I                          0x823B
+#define GL_RG32UI                         0x823C
+#define GL_VERTEX_ARRAY_BINDING           0x85B5
+#define GL_R8_SNORM                       0x8F94
+#define GL_RG8_SNORM                      0x8F95
+#define GL_RGB8_SNORM                     0x8F96
+#define GL_RGBA8_SNORM                    0x8F97
+#define GL_SIGNED_NORMALIZED              0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX  0x8D69
+#define GL_COPY_READ_BUFFER               0x8F36
+#define GL_COPY_WRITE_BUFFER              0x8F37
+#define GL_COPY_READ_BUFFER_BINDING       0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING      0x8F37
+#define GL_UNIFORM_BUFFER                 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING         0x8A28
+#define GL_UNIFORM_BUFFER_START           0x8A29
+#define GL_UNIFORM_BUFFER_SIZE            0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS      0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS    0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS    0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS    0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE         0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS          0x8A36
+#define GL_UNIFORM_TYPE                   0x8A37
+#define GL_UNIFORM_SIZE                   0x8A38
+#define GL_UNIFORM_NAME_LENGTH            0x8A39
+#define GL_UNIFORM_BLOCK_INDEX            0x8A3A
+#define GL_UNIFORM_OFFSET                 0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE           0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE          0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR           0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING          0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE        0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH      0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS  0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_INVALID_INDEX                  0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS   0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS  0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT        0x9111
+#define GL_OBJECT_TYPE                    0x9112
+#define GL_SYNC_CONDITION                 0x9113
+#define GL_SYNC_STATUS                    0x9114
+#define GL_SYNC_FLAGS                     0x9115
+#define GL_SYNC_FENCE                     0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE     0x9117
+#define GL_UNSIGNALED                     0x9118
+#define GL_SIGNALED                       0x9119
+#define GL_ALREADY_SIGNALED               0x911A
+#define GL_TIMEOUT_EXPIRED                0x911B
+#define GL_CONDITION_SATISFIED            0x911C
+#define GL_WAIT_FAILED                    0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT        0x00000001
+#define GL_TIMEOUT_IGNORED                0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR    0x88FE
+#define GL_ANY_SAMPLES_PASSED             0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_SAMPLER_BINDING                0x8919
+#define GL_RGB10_A2UI                     0x906F
+#define GL_TEXTURE_SWIZZLE_R              0x8E42
+#define GL_TEXTURE_SWIZZLE_G              0x8E43
+#define GL_TEXTURE_SWIZZLE_B              0x8E44
+#define GL_TEXTURE_SWIZZLE_A              0x8E45
+#define GL_GREEN                          0x1904
+#define GL_BLUE                           0x1905
+#define GL_INT_2_10_10_10_REV             0x8D9F
+#define GL_TRANSFORM_FEEDBACK             0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED      0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE      0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING     0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_BINARY_LENGTH          0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS     0x87FE
+#define GL_PROGRAM_BINARY_FORMATS         0x87FF
+#define GL_COMPRESSED_R11_EAC             0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC      0x9271
+#define GL_COMPRESSED_RG11_EAC            0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC     0x9273
+#define GL_COMPRESSED_RGB8_ETC2           0x9274
+#define GL_COMPRESSED_SRGB8_ETC2          0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC      0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT       0x912F
+#define GL_MAX_ELEMENT_INDEX              0x8D6B
+#define GL_NUM_SAMPLE_COUNTS              0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS       0x82DF
+typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params);
+typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays);
+typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
+typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array);
+typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data);
+typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode);
+typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index);
+typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
+typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
+typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
+typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data);
+typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params);
+typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
+typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers);
+typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
+typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id);
+typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids);
+typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids);
+typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id);
+typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src);
+GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices);
+GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels);
+GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data);
+GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids);
+GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id);
+GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glEndQuery (GLenum target);
+GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params);
+GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target);
+GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length);
+GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays);
+GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays);
+GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array);
+GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data);
+GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode);
+GL_APICALL void GL_APIENTRY glEndTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode);
+GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name);
+GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v);
+GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v);
+GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params);
+GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value);
+GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value);
+GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index);
+GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);
+GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName);
+GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
+GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount);
+GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags);
+GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync);
+GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync);
+GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout);
+GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
+GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data);
+GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params);
+GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers);
+GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers);
+GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler);
+GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler);
+GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param);
+GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor);
+GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id);
+GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids);
+GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids);
+GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id);
+GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void);
+GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary);
+GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length);
+GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments);
+GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params);
+#endif
+#endif /* GL_ES_VERSION_3_0 */
+
+#ifndef GL_ES_VERSION_3_1
+#define GL_ES_VERSION_3_1 1
+#define GL_COMPUTE_SHADER                 0x91B9
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS     0x91BB
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS     0x91BD
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS    0x8265
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT   0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE    0x91BF
+#define GL_COMPUTE_WORK_GROUP_SIZE        0x8267
+#define GL_DISPATCH_INDIRECT_BUFFER       0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_COMPUTE_SHADER_BIT             0x00000020
+#define GL_DRAW_INDIRECT_BUFFER           0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING   0x8F43
+#define GL_MAX_UNIFORM_LOCATIONS          0x826E
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH      0x9310
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT     0x9311
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES    0x9313
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_MAX_FRAMEBUFFER_WIDTH          0x9315
+#define GL_MAX_FRAMEBUFFER_HEIGHT         0x9316
+#define GL_MAX_FRAMEBUFFER_SAMPLES        0x9318
+#define GL_UNIFORM                        0x92E1
+#define GL_UNIFORM_BLOCK                  0x92E2
+#define GL_PROGRAM_INPUT                  0x92E3
+#define GL_PROGRAM_OUTPUT                 0x92E4
+#define GL_BUFFER_VARIABLE                0x92E5
+#define GL_SHADER_STORAGE_BLOCK           0x92E6
+#define GL_ATOMIC_COUNTER_BUFFER          0x92C0
+#define GL_TRANSFORM_FEEDBACK_VARYING     0x92F4
+#define GL_ACTIVE_RESOURCES               0x92F5
+#define GL_MAX_NAME_LENGTH                0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES       0x92F7
+#define GL_NAME_LENGTH                    0x92F9
+#define GL_TYPE                           0x92FA
+#define GL_ARRAY_SIZE                     0x92FB
+#define GL_OFFSET                         0x92FC
+#define GL_BLOCK_INDEX                    0x92FD
+#define GL_ARRAY_STRIDE                   0x92FE
+#define GL_MATRIX_STRIDE                  0x92FF
+#define GL_IS_ROW_MAJOR                   0x9300
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX    0x9301
+#define GL_BUFFER_BINDING                 0x9302
+#define GL_BUFFER_DATA_SIZE               0x9303
+#define GL_NUM_ACTIVE_VARIABLES           0x9304
+#define GL_ACTIVE_VARIABLES               0x9305
+#define GL_REFERENCED_BY_VERTEX_SHADER    0x9306
+#define GL_REFERENCED_BY_FRAGMENT_SHADER  0x930A
+#define GL_REFERENCED_BY_COMPUTE_SHADER   0x930B
+#define GL_TOP_LEVEL_ARRAY_SIZE           0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE         0x930D
+#define GL_LOCATION                       0x930E
+#define GL_VERTEX_SHADER_BIT              0x00000001
+#define GL_FRAGMENT_SHADER_BIT            0x00000002
+#define GL_ALL_SHADER_BITS                0xFFFFFFFF
+#define GL_PROGRAM_SEPARABLE              0x8258
+#define GL_ACTIVE_PROGRAM                 0x8259
+#define GL_PROGRAM_PIPELINE_BINDING       0x825A
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING  0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_START    0x92C2
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE     0x92C3
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS     0x92D2
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS   0x92D6
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS   0x92D7
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS  0x92D9
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER    0x92DB
+#define GL_MAX_IMAGE_UNITS                0x8F38
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS      0x90CA
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS    0x90CE
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS    0x90CF
+#define GL_IMAGE_BINDING_NAME             0x8F3A
+#define GL_IMAGE_BINDING_LEVEL            0x8F3B
+#define GL_IMAGE_BINDING_LAYERED          0x8F3C
+#define GL_IMAGE_BINDING_LAYER            0x8F3D
+#define GL_IMAGE_BINDING_ACCESS           0x8F3E
+#define GL_IMAGE_BINDING_FORMAT           0x906E
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+#define GL_ELEMENT_ARRAY_BARRIER_BIT      0x00000002
+#define GL_UNIFORM_BARRIER_BIT            0x00000004
+#define GL_TEXTURE_FETCH_BARRIER_BIT      0x00000008
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_COMMAND_BARRIER_BIT            0x00000040
+#define GL_PIXEL_BUFFER_BARRIER_BIT       0x00000080
+#define GL_TEXTURE_UPDATE_BARRIER_BIT     0x00000100
+#define GL_BUFFER_UPDATE_BARRIER_BIT      0x00000200
+#define GL_FRAMEBUFFER_BARRIER_BIT        0x00000400
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_ATOMIC_COUNTER_BARRIER_BIT     0x00001000
+#define GL_ALL_BARRIER_BITS               0xFFFFFFFF
+#define GL_IMAGE_2D                       0x904D
+#define GL_IMAGE_3D                       0x904E
+#define GL_IMAGE_CUBE                     0x9050
+#define GL_IMAGE_2D_ARRAY                 0x9053
+#define GL_INT_IMAGE_2D                   0x9058
+#define GL_INT_IMAGE_3D                   0x9059
+#define GL_INT_IMAGE_CUBE                 0x905B
+#define GL_INT_IMAGE_2D_ARRAY             0x905E
+#define GL_UNSIGNED_INT_IMAGE_2D          0x9063
+#define GL_UNSIGNED_INT_IMAGE_3D          0x9064
+#define GL_UNSIGNED_INT_IMAGE_CUBE        0x9066
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY    0x9069
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_READ_ONLY                      0x88B8
+#define GL_WRITE_ONLY                     0x88B9
+#define GL_READ_WRITE                     0x88BA
+#define GL_SHADER_STORAGE_BUFFER          0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING  0x90D3
+#define GL_SHADER_STORAGE_BUFFER_START    0x90D4
+#define GL_SHADER_STORAGE_BUFFER_SIZE     0x90D5
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE  0x90DE
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BARRIER_BIT     0x00002000
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_DEPTH_STENCIL_TEXTURE_MODE     0x90EA
+#define GL_STENCIL_INDEX                  0x1901
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_SAMPLE_POSITION                0x8E50
+#define GL_SAMPLE_MASK                    0x8E51
+#define GL_SAMPLE_MASK_VALUE              0x8E52
+#define GL_TEXTURE_2D_MULTISAMPLE         0x9100
+#define GL_MAX_SAMPLE_MASK_WORDS          0x8E59
+#define GL_MAX_COLOR_TEXTURE_SAMPLES      0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES      0x910F
+#define GL_MAX_INTEGER_SAMPLES            0x9110
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_SAMPLES                0x9106
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_WIDTH                  0x1000
+#define GL_TEXTURE_HEIGHT                 0x1001
+#define GL_TEXTURE_DEPTH                  0x8071
+#define GL_TEXTURE_INTERNAL_FORMAT        0x1003
+#define GL_TEXTURE_RED_SIZE               0x805C
+#define GL_TEXTURE_GREEN_SIZE             0x805D
+#define GL_TEXTURE_BLUE_SIZE              0x805E
+#define GL_TEXTURE_ALPHA_SIZE             0x805F
+#define GL_TEXTURE_DEPTH_SIZE             0x884A
+#define GL_TEXTURE_STENCIL_SIZE           0x88F1
+#define GL_TEXTURE_SHARED_SIZE            0x8C3F
+#define GL_TEXTURE_RED_TYPE               0x8C10
+#define GL_TEXTURE_GREEN_TYPE             0x8C11
+#define GL_TEXTURE_BLUE_TYPE              0x8C12
+#define GL_TEXTURE_ALPHA_TYPE             0x8C13
+#define GL_TEXTURE_DEPTH_TYPE             0x8C16
+#define GL_TEXTURE_COMPRESSED             0x86A1
+#define GL_SAMPLER_2D_MULTISAMPLE         0x9108
+#define GL_INT_SAMPLER_2D_MULTISAMPLE     0x9109
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_VERTEX_ATTRIB_BINDING          0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET  0x82D5
+#define GL_VERTEX_BINDING_DIVISOR         0x82D6
+#define GL_VERTEX_BINDING_OFFSET          0x82D7
+#define GL_VERTEX_BINDING_STRIDE          0x82D8
+#define GL_VERTEX_BINDING_BUFFER          0x8F4F
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS     0x82DA
+#define GL_MAX_VERTEX_ATTRIB_STRIDE       0x82E5
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param);
+typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name);
+typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program);
+typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program);
+typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings);
+typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines);
+typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines);
+typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline);
+typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val);
+typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex);
+typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
+GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect);
+GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect);
+GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect);
+GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param);
+GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params);
+GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name);
+GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params);
+GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name);
+GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program);
+GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program);
+GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings);
+GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines);
+GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines);
+GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0);
+GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1);
+GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value);
+GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
+GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline);
+GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data);
+GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers);
+GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
+GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val);
+GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params);
+GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
+GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
+GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex);
+GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor);
+#endif
+#endif /* GL_ES_VERSION_3_1 */
+
+#ifndef GL_ES_VERSION_3_2
+#define GL_ES_VERSION_3_2 1
+typedef void (GL_APIENTRY  *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#define GL_MULTISAMPLE_LINE_WIDTH_RANGE   0x9381
+#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY 0x9382
+#define GL_MULTIPLY                       0x9294
+#define GL_SCREEN                         0x9295
+#define GL_OVERLAY                        0x9296
+#define GL_DARKEN                         0x9297
+#define GL_LIGHTEN                        0x9298
+#define GL_COLORDODGE                     0x9299
+#define GL_COLORBURN                      0x929A
+#define GL_HARDLIGHT                      0x929B
+#define GL_SOFTLIGHT                      0x929C
+#define GL_DIFFERENCE                     0x929E
+#define GL_EXCLUSION                      0x92A0
+#define GL_HSL_HUE                        0x92AD
+#define GL_HSL_SATURATION                 0x92AE
+#define GL_HSL_COLOR                      0x92AF
+#define GL_HSL_LUMINOSITY                 0x92B0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS       0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION        0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM      0x8245
+#define GL_DEBUG_SOURCE_API               0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM     0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER   0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY       0x8249
+#define GL_DEBUG_SOURCE_APPLICATION       0x824A
+#define GL_DEBUG_SOURCE_OTHER             0x824B
+#define GL_DEBUG_TYPE_ERROR               0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR  0x824E
+#define GL_DEBUG_TYPE_PORTABILITY         0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE         0x8250
+#define GL_DEBUG_TYPE_OTHER               0x8251
+#define GL_DEBUG_TYPE_MARKER              0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP          0x8269
+#define GL_DEBUG_TYPE_POP_GROUP           0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION    0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH    0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH        0x826D
+#define GL_BUFFER                         0x82E0
+#define GL_SHADER                         0x82E1
+#define GL_PROGRAM                        0x82E2
+#define GL_VERTEX_ARRAY                   0x8074
+#define GL_QUERY                          0x82E3
+#define GL_PROGRAM_PIPELINE               0x82E4
+#define GL_SAMPLER                        0x82E6
+#define GL_MAX_LABEL_LENGTH               0x82E8
+#define GL_MAX_DEBUG_MESSAGE_LENGTH       0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES      0x9144
+#define GL_DEBUG_LOGGED_MESSAGES          0x9145
+#define GL_DEBUG_SEVERITY_HIGH            0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM          0x9147
+#define GL_DEBUG_SEVERITY_LOW             0x9148
+#define GL_DEBUG_OUTPUT                   0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT         0x00000002
+#define GL_STACK_OVERFLOW                 0x0503
+#define GL_STACK_UNDERFLOW                0x0504
+#define GL_GEOMETRY_SHADER                0x8DD9
+#define GL_GEOMETRY_SHADER_BIT            0x00000004
+#define GL_GEOMETRY_VERTICES_OUT          0x8916
+#define GL_GEOMETRY_INPUT_TYPE            0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE           0x8918
+#define GL_GEOMETRY_SHADER_INVOCATIONS    0x887F
+#define GL_LAYER_PROVOKING_VERTEX         0x825E
+#define GL_LINES_ADJACENCY                0x000A
+#define GL_LINE_STRIP_ADJACENCY           0x000B
+#define GL_TRIANGLES_ADJACENCY            0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY       0x000D
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS    0x8A2C
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS  0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES   0x8DE0
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS   0x92D5
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS    0x90CD
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_FIRST_VERTEX_CONVENTION        0x8E4D
+#define GL_LAST_VERTEX_CONVENTION         0x8E4E
+#define GL_UNDEFINED_VERTEX               0x8260
+#define GL_PRIMITIVES_GENERATED           0x8C87
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS     0x9312
+#define GL_MAX_FRAMEBUFFER_LAYERS         0x9317
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_REFERENCED_BY_GEOMETRY_SHADER  0x9309
+#define GL_PRIMITIVE_BOUNDING_BOX         0x92BE
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_FLAGS                  0x821E
+#define GL_LOSE_CONTEXT_ON_RESET          0x8252
+#define GL_GUILTY_CONTEXT_RESET           0x8253
+#define GL_INNOCENT_CONTEXT_RESET         0x8254
+#define GL_UNKNOWN_CONTEXT_RESET          0x8255
+#define GL_RESET_NOTIFICATION_STRATEGY    0x8256
+#define GL_NO_RESET_NOTIFICATION          0x8261
+#define GL_CONTEXT_LOST                   0x0507
+#define GL_SAMPLE_SHADING                 0x8C36
+#define GL_MIN_SAMPLE_SHADING_VALUE       0x8C37
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_PATCHES                        0x000E
+#define GL_PATCH_VERTICES                 0x8E72
+#define GL_TESS_CONTROL_OUTPUT_VERTICES   0x8E75
+#define GL_TESS_GEN_MODE                  0x8E76
+#define GL_TESS_GEN_SPACING               0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER          0x8E78
+#define GL_TESS_GEN_POINT_MODE            0x8E79
+#define GL_ISOLINES                       0x8E7A
+#define GL_QUADS                          0x0007
+#define GL_FRACTIONAL_ODD                 0x8E7B
+#define GL_FRACTIONAL_EVEN                0x8E7C
+#define GL_MAX_PATCH_VERTICES             0x8E7D
+#define GL_MAX_TESS_GEN_LEVEL             0x8E7E
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_PATCH_COMPONENTS      0x8E84
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_IS_PER_PATCH                   0x92E7
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_TESS_CONTROL_SHADER            0x8E88
+#define GL_TESS_EVALUATION_SHADER         0x8E87
+#define GL_TESS_CONTROL_SHADER_BIT        0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT     0x00000010
+#define GL_TEXTURE_BORDER_COLOR           0x1004
+#define GL_CLAMP_TO_BORDER                0x812D
+#define GL_TEXTURE_BUFFER                 0x8C2A
+#define GL_TEXTURE_BUFFER_BINDING         0x8C2A
+#define GL_MAX_TEXTURE_BUFFER_SIZE        0x8C2B
+#define GL_TEXTURE_BINDING_BUFFER         0x8C2C
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_SAMPLER_BUFFER                 0x8DC2
+#define GL_INT_SAMPLER_BUFFER             0x8DD0
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER    0x8DD8
+#define GL_IMAGE_BUFFER                   0x9051
+#define GL_INT_IMAGE_BUFFER               0x905C
+#define GL_UNSIGNED_INT_IMAGE_BUFFER      0x9067
+#define GL_TEXTURE_BUFFER_OFFSET          0x919D
+#define GL_TEXTURE_BUFFER_SIZE            0x919E
+#define GL_COMPRESSED_RGBA_ASTC_4x4       0x93B0
+#define GL_COMPRESSED_RGBA_ASTC_5x4       0x93B1
+#define GL_COMPRESSED_RGBA_ASTC_5x5       0x93B2
+#define GL_COMPRESSED_RGBA_ASTC_6x5       0x93B3
+#define GL_COMPRESSED_RGBA_ASTC_6x6       0x93B4
+#define GL_COMPRESSED_RGBA_ASTC_8x5       0x93B5
+#define GL_COMPRESSED_RGBA_ASTC_8x6       0x93B6
+#define GL_COMPRESSED_RGBA_ASTC_8x8       0x93B7
+#define GL_COMPRESSED_RGBA_ASTC_10x5      0x93B8
+#define GL_COMPRESSED_RGBA_ASTC_10x6      0x93B9
+#define GL_COMPRESSED_RGBA_ASTC_10x8      0x93BA
+#define GL_COMPRESSED_RGBA_ASTC_10x10     0x93BB
+#define GL_COMPRESSED_RGBA_ASTC_12x10     0x93BC
+#define GL_COMPRESSED_RGBA_ASTC_12x12     0x93BD
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC
+#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD
+#define GL_TEXTURE_CUBE_MAP_ARRAY         0x9009
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_SAMPLER_CUBE_MAP_ARRAY         0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW  0x900D
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY     0x900E
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+#define GL_IMAGE_CUBE_MAP_ARRAY           0x9054
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY       0x905F
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY   0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY   0x910B
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+typedef void (GL_APIENTRYP PFNGLBLENDBARRIERPROC) (void);
+typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void);
+typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params);
+typedef void (GL_APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode);
+typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst);
+typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+typedef void (GL_APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level);
+typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void);
+typedef void (GL_APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value);
+typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params);
+typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param);
+typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params);
+typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer);
+typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#if GL_GLES_PROTOTYPES
+GL_APICALL void GL_APIENTRY glBlendBarrier (void);
+GL_APICALL void GL_APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam);
+GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message);
+GL_APICALL void GL_APIENTRY glPopDebugGroup (void);
+GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label);
+GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params);
+GL_APICALL void GL_APIENTRY glEnablei (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDisablei (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glBlendEquationi (GLuint buf, GLenum mode);
+GL_APICALL void GL_APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+GL_APICALL void GL_APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst);
+GL_APICALL void GL_APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+GL_APICALL void GL_APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+GL_APICALL GLboolean GL_APIENTRY glIsEnabledi (GLenum target, GLuint index);
+GL_APICALL void GL_APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+GL_APICALL void GL_APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level);
+GL_APICALL void GL_APIENTRY glPrimitiveBoundingBox (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatus (void);
+GL_APICALL void GL_APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+GL_APICALL void GL_APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+GL_APICALL void GL_APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params);
+GL_APICALL void GL_APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+GL_APICALL void GL_APIENTRY glMinSampleShading (GLfloat value);
+GL_APICALL void GL_APIENTRY glPatchParameteri (GLenum pname, GLint value);
+GL_APICALL void GL_APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params);
+GL_APICALL void GL_APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param);
+GL_APICALL void GL_APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params);
+GL_APICALL void GL_APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params);
+GL_APICALL void GL_APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer);
+GL_APICALL void GL_APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+GL_APICALL void GL_APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+#endif
+#endif /* GL_ES_VERSION_3_2 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/opengl/include/GLES3/gl3platform.h b/opengl/include/GLES3/gl3platform.h
index 1bd1a85..b1e869d 100644
--- a/opengl/include/GLES3/gl3platform.h
+++ b/opengl/include/GLES3/gl3platform.h
@@ -1,7 +1,7 @@
 #ifndef __gl3platform_h_
 #define __gl3platform_h_
 
-/* $Revision: 18437 $ on $Date:: 2012-07-08 23:31:39 -0700 #$ */
+/* $Revision: 23328 $ on $Date:: 2013-10-02 02:28:28 -0700 #$ */
 
 /*
  * This document is licensed under the SGI Free Software B License Version
diff --git a/opengl/libagl/context.h b/opengl/libagl/context.h
index c599a55..d23f435 100644
--- a/opengl/libagl/context.h
+++ b/opengl/libagl/context.h
@@ -21,7 +21,7 @@
 #include <stddef.h>
 #include <sys/types.h>
 #include <pthread.h>
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
 #include <bionic_tls.h>
 #endif
 
@@ -579,7 +579,7 @@
 // state
 // ----------------------------------------------------------------------------
 
-#ifdef HAVE_ANDROID_OS
+#ifdef __ANDROID__
     // We have a dedicated TLS slot in bionic
     inline void setGlThreadSpecific(ogles_context_t *value) {
         __get_tls()[TLS_SLOT_OPENGL] = value;
diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index 593d0c2..7560d8f 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -64,7 +64,7 @@
 static pthread_mutex_t gInitMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_mutex_t gErrorKeyMutex = PTHREAD_MUTEX_INITIALIZER;
 static pthread_key_t gEGLErrorKey = -1;
-#ifndef HAVE_ANDROID_OS
+#ifndef __ANDROID__
 namespace gl {
 pthread_key_t gGLKey = -1;
 }; // namespace gl
@@ -1373,7 +1373,7 @@
 
     int32_t w = 0;
     int32_t h = 0;
-    while (attrib_list[0]) {
+    while (attrib_list[0] != EGL_NONE) {
         if (attrib_list[0] == EGL_WIDTH)  w = attrib_list[1];
         if (attrib_list[0] == EGL_HEIGHT) h = attrib_list[1];
         attrib_list+=2;
@@ -1403,7 +1403,7 @@
 
 EGLDisplay eglGetDisplay(NativeDisplayType display)
 {
-#ifndef HAVE_ANDROID_OS
+#ifndef __ANDROID__
     // this just needs to be done once
     if (gGLKey == -1) {
         pthread_mutex_lock(&gInitMutex);
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index 18ad300..eb86860 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -27,12 +27,11 @@
 	EGL/egl_object.cpp     \
 	EGL/egl.cpp 	       \
 	EGL/eglApi.cpp 	       \
-	EGL/trace.cpp              \
 	EGL/getProcAddress.cpp.arm \
 	EGL/Loader.cpp 	       \
 #
 
-LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libGLES_trace
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libui
 LOCAL_MODULE:= libEGL
 LOCAL_LDFLAGS += -Wl,--exclude-libs=ALL
 LOCAL_SHARED_LIBRARIES += libdl
@@ -42,7 +41,6 @@
 LOCAL_CFLAGS += -DLOG_TAG=\"libEGL\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 LOCAL_CFLAGS += -fvisibility=hidden
-LOCAL_CFLAGS += -DEGL_TRACE=1
 
 ifeq ($(BOARD_ALLOW_EGL_HIBERNATION),true)
   LOCAL_CFLAGS += -DBOARD_ALLOW_EGL_HIBERNATION
@@ -59,6 +57,11 @@
   LOCAL_CFLAGS += -DMAX_EGL_CACHE_SIZE=$(MAX_EGL_CACHE_SIZE)
 endif
 
+ifneq ($(filter address,$(SANITIZE_TARGET)),)
+  LOCAL_CFLAGS_32 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib\"
+  LOCAL_CFLAGS_64 += -DEGL_WRAPPER_DIR=\"/$(TARGET_COPY_OUT_DATA)/lib64\"
+endif
+
 LOCAL_REQUIRED_MODULES := $(egl.cfg_config_module)
 egl.cfg_config_module :=
 
@@ -98,11 +101,12 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_SRC_FILES:= 		\
-	GLES2/gl2.cpp.arm 	\
+LOCAL_SRC_FILES:= \
+	GLES2/gl2.cpp   \
 #
 
 LOCAL_CLANG := false
+LOCAL_ARM_MODE := arm
 LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
 LOCAL_MODULE:= libGLESv2
 
@@ -117,14 +121,32 @@
 # TODO: This is to work around b/20093774. Remove after root cause is fixed
 LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
 
-# Symlink libGLESv3.so -> libGLESv2.so
-# Platform modules should link against libGLESv2.so (-lGLESv2), but NDK apps
-# will be linked against libGLESv3.so.
-# Note we defer the evaluation of the LOCAL_POST_INSTALL_CMD,
-# so $(LOCAL_INSTALLED_MODULE) will be expanded to correct value,
-# even for both 32-bit and 64-bit installed files in multilib build.
-LOCAL_POST_INSTALL_CMD = \
-    $(hide) ln -sf $(notdir $(LOCAL_INSTALLED_MODULE)) $(dir $(LOCAL_INSTALLED_MODULE))libGLESv3.so
+include $(BUILD_SHARED_LIBRARY)
+
+###############################################################################
+# Build the wrapper OpenGL ES 3.x library (this is just different name for v2)
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	GLES2/gl2.cpp   \
+#
+
+LOCAL_CLANG := false
+LOCAL_ARM_MODE := arm
+LOCAL_SHARED_LIBRARIES += libcutils libutils liblog libEGL
+LOCAL_MODULE:= libGLESv3
+LOCAL_SHARED_LIBRARIES += libdl
+# we need to access the private Bionic header <bionic_tls.h>
+LOCAL_C_INCLUDES += bionic/libc/private
+
+LOCAL_CFLAGS += -DLOG_TAG=\"libGLESv3\"
+LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS += -fvisibility=hidden
+
+# TODO: This is to work around b/20093774. Remove after root cause is fixed
+LOCAL_LDFLAGS_arm += -Wl,--hash-style,both
 
 include $(BUILD_SHARED_LIBRARY)
 
@@ -139,6 +161,7 @@
 #
 
 LOCAL_MODULE:= libETC1
+LOCAL_MODULE_HOST_OS := darwin linux windows
 
 include $(BUILD_HOST_STATIC_LIBRARY)
 
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 1fcc048..49f501d 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -28,8 +28,6 @@
 
 #include <EGL/egl.h>
 
-#include "../glestrace.h"
-
 #include "egldefs.h"
 #include "Loader.h"
 
@@ -70,7 +68,9 @@
  *  -1   -> not running inside the emulator
  *   0   -> running inside the emulator, but GPU emulation not supported
  *   1   -> running inside the emulator, GPU emulation is supported
- *          through the "emulation" config.
+ *          through the "emulation" host-side OpenGL ES implementation.
+ *   2   -> running inside the emulator, GPU emulation is supported
+ *          through a guest-side vendor driver's OpenGL ES implementation.
  */
 static int
 checkGlesEmulationStatus(void)
@@ -92,7 +92,7 @@
         return -1;
 
     /* We are in the emulator, get GPU status value */
-    property_get("ro.kernel.qemu.gles",prop,"0");
+    property_get("qemu.gles",prop,"0");
     return atoi(prop);
 }
 
@@ -158,7 +158,6 @@
 }
 
 Loader::~Loader() {
-    GLTrace_stop();
 }
 
 static void* load_wrapper(const char* path) {
@@ -167,11 +166,53 @@
     return so;
 }
 
+#ifndef EGL_WRAPPER_DIR
+#if defined(__LP64__)
+#define EGL_WRAPPER_DIR "/system/lib64"
+#else
+#define EGL_WRAPPER_DIR "/system/lib"
+#endif
+#endif
+
+static void setEmulatorGlesValue(void) {
+    char prop[PROPERTY_VALUE_MAX];
+    property_get("ro.kernel.qemu", prop, "0");
+    if (atoi(prop) != 1) return;
+
+    property_get("ro.kernel.qemu.gles",prop,"0");
+    if (atoi(prop) == 1) {
+        ALOGD("Emulator has host GPU support, qemu.gles is set to 1.");
+        property_set("qemu.gles", "1");
+        return;
+    }
+
+    // for now, checking the following
+    // directory is good enough for emulator system images
+    const char* vendor_lib_path =
+#if defined(__LP64__)
+        "/vendor/lib64/egl";
+#else
+        "/vendor/lib/egl";
+#endif
+
+    const bool has_vendor_lib = (access(vendor_lib_path, R_OK) == 0);
+    if (has_vendor_lib) {
+        ALOGD("Emulator has vendor provided software renderer, qemu.gles is set to 2.");
+        property_set("qemu.gles", "2");
+    } else {
+        ALOGD("Emulator without GPU support detected. "
+              "Fallback to legacy software renderer, qemu.gles is set to 0.");
+        property_set("qemu.gles", "0");
+    }
+}
+
 void* Loader::open(egl_connection_t* cnx)
 {
     void* dso;
     driver_t* hnd = 0;
 
+    setEmulatorGlesValue();
+
     dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
     if (dso) {
         hnd = new driver_t(dso);
@@ -187,15 +228,10 @@
 
     LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
 
-#if defined(__LP64__)
-    cnx->libEgl   = load_wrapper("/system/lib64/libEGL.so");
-    cnx->libGles2 = load_wrapper("/system/lib64/libGLESv2.so");
-    cnx->libGles1 = load_wrapper("/system/lib64/libGLESv1_CM.so");
-#else
-    cnx->libEgl   = load_wrapper("/system/lib/libEGL.so");
-    cnx->libGles2 = load_wrapper("/system/lib/libGLESv2.so");
-    cnx->libGles1 = load_wrapper("/system/lib/libGLESv1_CM.so");
-#endif
+    cnx->libEgl   = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
+    cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
+    cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+
     LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
             "couldn't load system EGL wrapper libraries");
 
@@ -275,6 +311,28 @@
     public:
         static String8 find(const char* kind) {
             String8 result;
+            int emulationStatus = checkGlesEmulationStatus();
+            switch (emulationStatus) {
+                case 0:
+#if defined(__LP64__)
+                    result.setTo("/system/lib64/egl/libGLES_android.so");
+#else
+                    result.setTo("/system/lib/egl/libGLES_android.so");
+#endif
+                    return result;
+                case 1:
+                    // Use host-side OpenGL through the "emulation" library
+#if defined(__LP64__)
+                    result.appendFormat("/system/lib64/egl/lib%s_emulation.so", kind);
+#else
+                    result.appendFormat("/system/lib/egl/lib%s_emulation.so", kind);
+#endif
+                    return result;
+                default:
+                    // Not in emulator, or use other guest-side implementation
+                    break;
+            }
+
             String8 pattern;
             pattern.appendFormat("lib%s", kind);
             const char* const searchPaths[] = {
@@ -319,20 +377,6 @@
     private:
         static bool find(String8& result,
                 const String8& pattern, const char* const search, bool exact) {
-
-            // in the emulator case, we just return the hardcoded name
-            // of the software renderer.
-            if (checkGlesEmulationStatus() == 0) {
-                ALOGD("Emulator without GPU support detected. "
-                      "Fallback to software renderer.");
-#if defined(__LP64__)
-                result.setTo("/system/lib64/egl/libGLES_android.so");
-#else
-                result.setTo("/system/lib/egl/libGLES_android.so");
-#endif
-                return true;
-            }
-
             if (exact) {
                 String8 absolutePath;
                 absolutePath.appendFormat("%s/%s.so", search, pattern.string());
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 4e0e5bc..18cf261 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -32,7 +32,6 @@
 #include <utils/String8.h>
 
 #include "../egl_impl.h"
-#include "../glestrace.h"
 
 #include "egl_tls.h"
 #include "egldefs.h"
@@ -54,161 +53,10 @@
 
 // ----------------------------------------------------------------------------
 
-#if EGL_TRACE
-
-EGLAPI pthread_key_t gGLTraceKey = -1;
-
-// ----------------------------------------------------------------------------
-
-/**
- * There are three different tracing methods:
- * 1. libs/EGL/trace.cpp: Traces all functions to systrace.
- *    To enable:
- *      - set system property "debug.egl.trace" to "systrace" to trace all apps.
- * 2. libs/EGL/trace.cpp: Logs a stack trace for GL errors after each function call.
- *    To enable:
- *      - set system property "debug.egl.trace" to "error" to trace all apps.
- * 3. libs/EGL/trace.cpp: Traces all functions to logcat.
- *    To enable:
- *      - set system property "debug.egl.trace" to 1 to trace all apps.
- *      - or call setGLTraceLevel(1) from an app to enable tracing for that app.
- * 4. libs/GLES_trace: Traces all functions via protobuf to host.
- *    To enable:
- *        - set system property "debug.egl.debug_proc" to the application name.
- *      - or call setGLDebugLevel(1) from the app.
- */
-static int sEGLTraceLevel;
-static int sEGLApplicationTraceLevel;
-
-static bool sEGLSystraceEnabled;
-static bool sEGLGetErrorEnabled;
-
-static volatile int sEGLDebugLevel;
-
-extern gl_hooks_t gHooksTrace;
-extern gl_hooks_t gHooksSystrace;
-extern gl_hooks_t gHooksErrorTrace;
-
-int getEGLDebugLevel() {
-    return sEGLDebugLevel;
-}
-
-void setEGLDebugLevel(int level) {
-    sEGLDebugLevel = level;
-}
-
-static inline void setGlTraceThreadSpecific(gl_hooks_t const *value) {
-    pthread_setspecific(gGLTraceKey, value);
-}
-
-gl_hooks_t const* getGLTraceThreadSpecific() {
-    return static_cast<gl_hooks_t*>(pthread_getspecific(gGLTraceKey));
-}
-
-void initEglTraceLevel() {
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.egl.trace", value, "0");
-
-    sEGLGetErrorEnabled = !strcasecmp(value, "error");
-    if (sEGLGetErrorEnabled) {
-        sEGLSystraceEnabled = false;
-        sEGLTraceLevel = 0;
-        return;
-    }
-
-    sEGLSystraceEnabled = !strcasecmp(value, "systrace");
-    if (sEGLSystraceEnabled) {
-        sEGLTraceLevel = 0;
-        return;
-    }
-
-    int propertyLevel = atoi(value);
-    int applicationLevel = sEGLApplicationTraceLevel;
-    sEGLTraceLevel = propertyLevel > applicationLevel ? propertyLevel : applicationLevel;
-}
-
-void initEglDebugLevel() {
-    if (getEGLDebugLevel() == 0) {
-        char value[PROPERTY_VALUE_MAX];
-
-        // check system property only on userdebug or eng builds
-        property_get("ro.debuggable", value, "0");
-        if (value[0] == '0')
-            return;
-
-        property_get("debug.egl.debug_proc", value, "");
-        if (strlen(value) > 0) {
-            FILE * file = fopen("/proc/self/cmdline", "r");
-            if (file) {
-                char cmdline[256];
-                if (fgets(cmdline, sizeof(cmdline), file)) {
-                    if (!strncmp(value, cmdline, strlen(value))) {
-                        // set EGL debug if the "debug.egl.debug_proc" property
-                        // matches the prefix of this application's command line
-                        setEGLDebugLevel(1);
-                    }
-                }
-                fclose(file);
-            }
-        }
-    }
-
-    if (getEGLDebugLevel() > 0) {
-        if (GLTrace_start() < 0) {
-            ALOGE("Error starting Tracer for OpenGL ES. Disabling..");
-            setEGLDebugLevel(0);
-        }
-    }
-}
-
-void setGLHooksThreadSpecific(gl_hooks_t const *value) {
-    if (sEGLGetErrorEnabled) {
-        setGlTraceThreadSpecific(value);
-        setGlThreadSpecific(&gHooksErrorTrace);
-    } else if (sEGLSystraceEnabled) {
-        setGlTraceThreadSpecific(value);
-        setGlThreadSpecific(&gHooksSystrace);
-    } else if (sEGLTraceLevel > 0) {
-        setGlTraceThreadSpecific(value);
-        setGlThreadSpecific(&gHooksTrace);
-    } else if (getEGLDebugLevel() > 0 && value != &gHooksNoContext) {
-        setGlTraceThreadSpecific(value);
-        setGlThreadSpecific(GLTrace_getGLHooks());
-    } else {
-        setGlTraceThreadSpecific(NULL);
-        setGlThreadSpecific(value);
-    }
-}
-
-/*
- * Global entry point to allow applications to modify their own trace level.
- * The effective trace level is the max of this level and the value of debug.egl.trace.
- */
-extern "C"
-void setGLTraceLevel(int level) {
-    sEGLApplicationTraceLevel = level;
-}
-
-/*
- * Global entry point to allow applications to modify their own debug level.
- * Debugging is enabled if either the application requested it, or if the system property
- * matches the application's name.
- * Note that this only sets the debug level. The value is read and used either in
- * initEglDebugLevel() if the application hasn't initialized its display yet, or when
- * eglSwapBuffers() is called next.
- */
-void EGLAPI setGLDebugLevel(int level) {
-    setEGLDebugLevel(level);
-}
-
-#else
-
 void setGLHooksThreadSpecific(gl_hooks_t const *value) {
     setGlThreadSpecific(value);
 }
 
-#endif
-
 /*****************************************************************************/
 
 static int gl_no_context() {
@@ -231,10 +79,6 @@
 
 static void early_egl_init(void)
 {
-#if EGL_TRACE
-    pthread_key_create(&gGLTraceKey, NULL);
-    initEglTraceLevel();
-#endif
     int numHooks = sizeof(gHooksNoContext) / sizeof(EGLFuncPointer);
     EGLFuncPointer *iter = reinterpret_cast<EGLFuncPointer*>(&gHooksNoContext);
     for (int hook = 0; hook < numHooks; ++hook) {
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index cdec565..00bfc24 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -33,13 +33,14 @@
 #include <cutils/properties.h>
 #include <cutils/memory.h>
 
+#include <ui/GraphicBuffer.h>
+
 #include <utils/KeyedVector.h>
 #include <utils/SortedVector.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
 
 #include "../egl_impl.h"
-#include "../glestrace.h"
 #include "../hooks.h"
 
 #include "egl_display.h"
@@ -71,7 +72,7 @@
  * The rest (gExtensionString) depend on support in the EGL driver, and are
  * only available if the driver supports them. However, some of these must be
  * supported because they are used by the Android system itself; these are
- * listd as mandatory below and are required by the CDD. The system *assumes*
+ * listed as mandatory below and are required by the CDD. The system *assumes*
  * the mandatory extensions are present and may not function properly if some
  * are missing.
  *
@@ -81,6 +82,8 @@
         "EGL_KHR_get_all_proc_addresses "
         "EGL_ANDROID_presentation_time "
         "EGL_KHR_swap_buffers_with_damage "
+        "EGL_ANDROID_create_native_client_buffer "
+        "EGL_ANDROID_front_buffer_auto_refresh "
         ;
 extern char const * const gExtensionString  =
         "EGL_KHR_image "                        // mandatory
@@ -112,6 +115,9 @@
         "EGL_KHR_partial_update "               // strongly recommended
         "EGL_EXT_buffer_age "                   // strongly recommended with partial_update
         "EGL_KHR_create_context_no_error "
+        "EGL_KHR_mutable_render_buffer "
+        "EGL_EXT_yuv_surface "
+        "EGL_EXT_protected_content "
         ;
 
 // extensions not exposed to applications but used by the ANDROID system
@@ -169,6 +175,10 @@
     { "eglSwapBuffersWithDamageKHR",
             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
 
+    // EGL_ANDROID_native_client_buffer
+    { "eglCreateNativeClientBufferANDROID",
+            (__eglMustCastToProperFunctionPointerType)&eglCreateNativeClientBufferANDROID },
+
     // EGL_KHR_partial_update
     { "eglSetDamageRegionKHR",
             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
@@ -231,8 +241,6 @@
 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
 extern EGLBoolean egl_init_drivers();
 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
-extern int getEGLDebugLevel();
-extern void setEGLDebugLevel(int level);
 extern gl_hooks_t gHooksTrace;
 
 } // namespace android;
@@ -674,10 +682,6 @@
             }
             egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
                     version);
-#if EGL_TRACE
-            if (getEGLDebugLevel() > 0)
-                GLTrace_eglCreateContext(version, c);
-#endif
             return c;
         }
     }
@@ -783,10 +787,6 @@
         if (c) {
             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
             egl_tls_t::setContext(ctx);
-#if EGL_TRACE
-            if (getEGLDebugLevel() > 0)
-                GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
-#endif
             _c.acquire();
             _r.acquire();
             _d.acquire();
@@ -971,10 +971,6 @@
                 "no more slots for eglGetProcAddress(\"%s\")",
                 procname);
 
-#if EGL_TRACE
-        gl_hooks_t *debugHooks = GLTrace_getGLHooks();
-#endif
-
         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
             bool found = false;
 
@@ -984,10 +980,6 @@
                 addr =
                 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
                 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
-#if EGL_TRACE
-                debugHooks->ext.extensions[slot] =
-                gHooksTrace.ext.extensions[slot] =
-#endif
                         cnx->egl.eglGetProcAddress(procname);
                 if (addr) found = true;
             }
@@ -1079,34 +1071,6 @@
     if (!_s.get())
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
-#if EGL_TRACE
-    gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
-    if (getEGLDebugLevel() > 0) {
-        if (trace_hooks == NULL) {
-            if (GLTrace_start() < 0) {
-                ALOGE("Disabling Tracer for OpenGL ES");
-                setEGLDebugLevel(0);
-            } else {
-                // switch over to the trace version of hooks
-                EGLContext ctx = egl_tls_t::getContext();
-                egl_context_t * const c = get_context(ctx);
-                if (c) {
-                    setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
-                    GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
-                }
-            }
-        }
-
-        GLTrace_eglSwapBuffers(dpy, draw);
-    } else if (trace_hooks != NULL) {
-        // tracing is now disabled, so switch back to the non trace version
-        EGLContext ctx = egl_tls_t::getContext();
-        egl_context_t * const c = get_context(ctx);
-        if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
-        GLTrace_stop();
-    }
-#endif
-
     egl_surface_t const * const s = get_surface(draw);
 
     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
@@ -1233,6 +1197,14 @@
         return setError(EGL_BAD_SURFACE, EGL_FALSE);
 
     egl_surface_t const * const s = get_surface(surface);
+
+    if (attribute == EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID) {
+        int err = native_window_set_auto_refresh(s->win.get(),
+            value ? true : false);
+        return (err == NO_ERROR) ? EGL_TRUE :
+            setError(EGL_BAD_SURFACE, EGL_FALSE);
+    }
+
     if (s->cnx->egl.eglSurfaceAttrib) {
         return s->cnx->egl.eglSurfaceAttrib(
                 dp->disp.dpy, s->surface, attribute, value);
@@ -1356,11 +1328,6 @@
 {
     clearError();
 
-#if EGL_TRACE
-    if (getEGLDebugLevel() > 0)
-        GLTrace_eglReleaseThread();
-#endif
-
     // If there is context bound to the thread, release it
     egl_display_t::loseCurrent(get_context(getContext()));
 
@@ -1814,6 +1781,93 @@
     return EGL_TRUE;
 }
 
+EGLClientBuffer eglCreateNativeClientBufferANDROID(const EGLint *attrib_list)
+{
+    clearError();
+
+    int usage = 0;
+    uint32_t width = 0;
+    uint32_t height = 0;
+    uint32_t format = 0;
+    uint32_t red_size = 0;
+    uint32_t green_size = 0;
+    uint32_t blue_size = 0;
+    uint32_t alpha_size = 0;
+
+#define GET_POSITIVE_VALUE(case_name, target) \
+    case case_name: \
+        if (value > 0) { \
+            target = value; \
+        } else { \
+            return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0); \
+        } \
+        break
+
+    if (attrib_list) {
+        while (*attrib_list != EGL_NONE) {
+            GLint attr = *attrib_list++;
+            GLint value = *attrib_list++;
+            switch (attr) {
+                GET_POSITIVE_VALUE(EGL_WIDTH, width);
+                GET_POSITIVE_VALUE(EGL_HEIGHT, height);
+                GET_POSITIVE_VALUE(EGL_RED_SIZE, red_size);
+                GET_POSITIVE_VALUE(EGL_GREEN_SIZE, green_size);
+                GET_POSITIVE_VALUE(EGL_BLUE_SIZE, blue_size);
+                GET_POSITIVE_VALUE(EGL_ALPHA_SIZE, alpha_size);
+                case EGL_NATIVE_BUFFER_USAGE_ANDROID:
+                    if (value & EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID) {
+                        usage |= GRALLOC_USAGE_PROTECTED;
+                    }
+                    if (value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) {
+                        usage |= GRALLOC_USAGE_HW_RENDER;
+                    }
+                    if (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID) {
+                        usage |= GRALLOC_USAGE_HW_TEXTURE;
+                    }
+                    // The buffer must be used for either a texture or a
+                    // renderbuffer.
+                    if ((value & EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID) &&
+                        (value & EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) {
+                        return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+                    }
+                    break;
+                default:
+                    return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+            }
+        }
+    }
+#undef GET_POSITIVE_VALUE
+
+    // Validate format.
+    if (red_size == 8 && green_size == 8 && blue_size == 8) {
+        if (alpha_size == 8) {
+            format = HAL_PIXEL_FORMAT_RGBA_8888;
+        } else {
+            format = HAL_PIXEL_FORMAT_RGB_888;
+        }
+    } else if (red_size == 5 && green_size == 6 && blue_size == 5 &&
+               alpha_size == 0) {
+        format == HAL_PIXEL_FORMAT_RGB_565;
+    } else {
+        ALOGE("Invalid native pixel format { r=%d, g=%d, b=%d, a=%d }",
+                red_size, green_size, blue_size, alpha_size);
+        return setError(EGL_BAD_PARAMETER, (EGLClientBuffer)0);
+    }
+
+    GraphicBuffer* gBuffer = new GraphicBuffer(width, height, format, usage);
+    const status_t err = gBuffer->initCheck();
+    if (err != NO_ERROR) {
+        ALOGE("Unable to create native buffer { w=%d, h=%d, f=%d, u=%#x }: %#x",
+                width, height, format, usage, err);
+        // Destroy the buffer.
+        sp<GraphicBuffer> holder(gBuffer);
+        return setError(EGL_BAD_ALLOC, (EGLClientBuffer)0);
+    }
+    ALOGD("Created new native buffer %p { w=%d, h=%d, f=%d, u=%#x }",
+            gBuffer, width, height, format, usage);
+    return static_cast<EGLClientBuffer>(gBuffer->getNativeBuffer());
+}
+
 // ----------------------------------------------------------------------------
 // NVIDIA extensions
 // ----------------------------------------------------------------------------
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index b0798a1..8c135c8 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -21,6 +21,7 @@
 #include "egldefs.h"
 
 #include <fcntl.h>
+#include <inttypes.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -164,7 +165,7 @@
             // running, so there's no need to keep a ref around.
             sp<Thread> deferredSaveThread(new DeferredSaveThread());
             mSavePending = true;
-            deferredSaveThread->run();
+            deferredSaveThread->run("DeferredSaveThread");
         }
     }
 }
@@ -306,7 +307,8 @@
         // Sanity check the size before trying to mmap it.
         size_t fileSize = statBuf.st_size;
         if (fileSize > maxTotalSize * 2) {
-            ALOGE("cache file is too large: %#llx", statBuf.st_size);
+            ALOGE("cache file is too large: %#" PRIx64,
+                  static_cast<off64_t>(statBuf.st_size));
             close(fd);
             return;
         }
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index ec59235..e335a6c 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -38,17 +38,16 @@
 extern char const * const gBuiltinExtensionString;
 extern char const * const gExtensionString;
 
-extern void initEglTraceLevel();
-extern void initEglDebugLevel();
 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
 
 // ----------------------------------------------------------------------------
 
 static bool findExtension(const char* exts, const char* name, size_t nameLen) {
     if (exts) {
-        const char* match = strstr(exts, name);
-        if (match && (match[nameLen] == '\0' || match[nameLen] == ' ')) {
-            return true;
+        for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
+            if (match[nameLen] == '\0' || match[nameLen] == ' ') {
+                return true;
+            }
         }
     }
     return false;
@@ -139,15 +138,6 @@
     {
         Mutex::Autolock _l(lock);
 
-#if EGL_TRACE
-
-        // Called both at early_init time and at this time. (Early_init is pre-zygote, so
-        // the information from that call may be stale.)
-        initEglTraceLevel();
-        initEglDebugLevel();
-
-#endif
-
         setGLHooksThreadSpecific(&gHooksNoContext);
 
         // initialize each EGL and
@@ -189,25 +179,21 @@
 
         mExtensionString.setTo(gBuiltinExtensionString);
         char const* start = gExtensionString;
-        char const* end;
         do {
-            // find the space separating this extension for the next one
-            end = strchr(start, ' ');
-            if (end) {
-                // length of the extension string
-                const size_t len = end - start;
-                if (len) {
-                    // NOTE: we could avoid the copy if we had strnstr.
-                    const String8 ext(start, len);
-                    if (findExtension(disp.queryString.extensions, ext.string(),
-                            len)) {
-                        mExtensionString.append(start, len+1);
-                    }
+            // length of the extension name
+            size_t len = strcspn(start, " ");
+            if (len) {
+                // NOTE: we could avoid the copy if we had strnstr.
+                const String8 ext(start, len);
+                if (findExtension(disp.queryString.extensions, ext.string(),
+                        len)) {
+                    mExtensionString.append(ext + " ");
                 }
-                // process the next extension string, and skip the space.
-                start = end + 1;
+                // advance to the next extension name, skipping the space.
+                start += len;
+                start += (*start == ' ') ? 1 : 0;
             }
-        } while (end);
+        } while (*start != '\0');
 
         egl_cache_t::get()->initialize(this);
 
@@ -286,7 +272,7 @@
         // there are no reference to them, it which case, we're free to
         // delete them.
         size_t count = objects.size();
-        ALOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
+        ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count);
         for (size_t i=0 ; i<count ; i++) {
             egl_object_t* o = objects.itemAt(i);
             o->destroy();
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 498b2fc..2b56718 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -80,6 +80,7 @@
 EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
 EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
 EGL_ENTRY(EGLint, eglDupNativeFenceFDANDROID, EGLDisplay, EGLSyncKHR)
+EGL_ENTRY(EGLClientBuffer, eglCreateNativeClientBufferANDROID, const EGLint *)
 
 /* NVIDIA extensions */
 
diff --git a/opengl/libs/EGL/egl_object.cpp b/opengl/libs/EGL/egl_object.cpp
index 918faa8..90f27d1 100644
--- a/opengl/libs/EGL/egl_object.cpp
+++ b/opengl/libs/EGL/egl_object.cpp
@@ -67,7 +67,8 @@
 egl_surface_t::egl_surface_t(egl_display_t* dpy, EGLConfig config,
         EGLNativeWindowType win, EGLSurface surface,
         egl_connection_t const* cnx) :
-    egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx)
+    egl_object_t(dpy), surface(surface), config(config), win(win), cnx(cnx),
+    connected(true)
 {
     if (win) {
         getDisplay()->onWindowSurfaceCreated();
@@ -77,14 +78,27 @@
 egl_surface_t::~egl_surface_t() {
     ANativeWindow* const window = win.get();
     if (window != NULL) {
+        disconnect();
+        getDisplay()->onWindowSurfaceDestroyed();
+    }
+}
+
+void egl_surface_t::disconnect() {
+    ANativeWindow* const window = win.get();
+    if (window != NULL && connected) {
         native_window_set_buffers_format(window, 0);
         if (native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL)) {
             ALOGW("EGLNativeWindowType %p disconnect failed", window);
         }
-        getDisplay()->onWindowSurfaceDestroyed();
+        connected = false;
     }
 }
 
+void egl_surface_t::terminate() {
+    disconnect();
+    egl_object_t::terminate();
+}
+
 // ----------------------------------------------------------------------------
 
 egl_context_t::egl_context_t(EGLDisplay dpy, EGLContext context, EGLConfig config,
diff --git a/opengl/libs/EGL/egl_object.h b/opengl/libs/EGL/egl_object.h
index f5a9f58..673b7da 100644
--- a/opengl/libs/EGL/egl_object.h
+++ b/opengl/libs/EGL/egl_object.h
@@ -37,7 +37,7 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
-struct egl_display_t;
+class egl_display_t;
 
 class egl_object_t {
     egl_display_t *display;
@@ -45,6 +45,7 @@
 
 protected:
     virtual ~egl_object_t();
+    virtual void terminate();
 
 public:
     egl_object_t(egl_display_t* display);
@@ -55,7 +56,6 @@
     inline egl_display_t* getDisplay() const { return display; }
 
 private:
-    void terminate();
     static bool get(egl_display_t const* display, egl_object_t* object);
 
 public:
@@ -127,6 +127,7 @@
 class egl_surface_t : public egl_object_t {
 protected:
     ~egl_surface_t();
+    void terminate() override;
 public:
     typedef egl_object_t::LocalRef<egl_surface_t, EGLSurface> Ref;
 
@@ -138,6 +139,9 @@
     EGLConfig config;
     sp<ANativeWindow> win;
     egl_connection_t const* cnx;
+private:
+    bool connected;
+    void disconnect();
 };
 
 class egl_context_t: public egl_object_t {
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
index 5af4f5b..00eae0b 100644
--- a/opengl/libs/EGL/egl_tls.h
+++ b/opengl/libs/EGL/egl_tls.h
@@ -68,14 +68,6 @@
     egl_tls_t::setErrorEtc(__FUNCTION__, __LINE__, _e, _r, true)
 
 // ----------------------------------------------------------------------------
-
-#if EGL_TRACE
-
-extern gl_hooks_t const* getGLTraceThreadSpecific();
-
-#endif
-
-// ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
 
diff --git a/opengl/libs/EGL/getProcAddress.cpp b/opengl/libs/EGL/getProcAddress.cpp
index 660af33..bdfd21c 100644
--- a/opengl/libs/EGL/getProcAddress.cpp
+++ b/opengl/libs/EGL/getProcAddress.cpp
@@ -45,13 +45,14 @@
             GET_TLS(r12)                                        \
             "ldr   r12, [r12, %[tls]] \n"                       \
             "cmp   r12, #0            \n"                       \
-            "ldrne r12, [r12, %[api]] \n"                       \
+            "addne r12, %[api]        \n"                       \
+            "ldrne r12, [r12]         \n"                       \
             "cmpne r12, #0            \n"                       \
             "bxne  r12                \n"                       \
             "bx    lr                 \n"                       \
             :                                                   \
             : [tls] "J"(TLS_SLOT_OPENGL_API*4),                 \
-              [api] "J"(__builtin_offsetof(gl_hooks_t,          \
+              [api] "r"(__builtin_offsetof(gl_hooks_t,          \
                                       ext.extensions[_api]))    \
             : "r12"                                             \
             );
diff --git a/opengl/libs/EGL/trace.cpp b/opengl/libs/EGL/trace.cpp
deleted file mode 100644
index 4f07053..0000000
--- a/opengl/libs/EGL/trace.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-/*
- ** Copyright 2010, The Android Open Source Project
- **
- ** 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.
- */
-
-#if EGL_TRACE
-
-#include <stdarg.h>
-#include <stdlib.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#include <cutils/log.h>
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include <utils/Trace.h>
-
-#include <utils/CallStack.h>
-
-#include "egl_tls.h"
-#include "hooks.h"
-
-// ----------------------------------------------------------------------------
-namespace android {
-// ----------------------------------------------------------------------------
-
-struct GLenumString {
-    // The GL_TIMEOUT_IGNORED "enum" doesn't fit in a GLenum, so use GLuint64
-    GLuint64 e;
-    const char* s;
-};
-
-#undef GL_ENUM
-#define GL_ENUM(VAL,NAME) {VAL, #NAME},
-
-static GLenumString g_enumnames[] = {
-#include "enums.in"
-};
-#undef GL_ENUM
-
-static int compareGLEnum(const void* a, const void* b) {
-    return ((const GLenumString*) a)->e - ((const GLenumString*) b)->e;
-}
-
-static const char* GLEnumToString(GLenum e) {
-    GLenumString key = {e, ""};
-    const GLenumString* result = (const GLenumString*) bsearch(
-        &key, g_enumnames,
-        sizeof(g_enumnames) / sizeof(g_enumnames[0]),
-        sizeof(g_enumnames[0]), compareGLEnum);
-    if (result) {
-        return result->s;
-    }
-    return NULL;
-}
-
-static const char* GLbooleanToString(GLboolean arg) {
-    return arg ? "GL_TRUE" : "GL_FALSE";
-}
-
-static GLenumString g_bitfieldNames[] = {
-    {0x00004000, "GL_COLOR_BUFFER_BIT"},
-    {0x00000400, "GL_STENCIL_BUFFER_BIT"},
-    {0x00000100, "GL_DEPTH_BUFFER_BIT"}
-};
-
-class StringBuilder {
-    static const int lineSize = 500;
-    char line[lineSize];
-    int line_index;
-public:
-    StringBuilder() {
-        line_index = 0;
-        line[0] = '\0';
-    }
-    void append(const char* fmt, ...) {
-        va_list argp;
-        va_start(argp, fmt);
-        line_index += vsnprintf(line + line_index, lineSize-line_index, fmt, argp);
-        va_end(argp);
-    }
-    const char* getString() {
-        line_index = 0;
-        line[lineSize-1] = '\0';
-        return line;
-    }
-};
-
-
-static void TraceGLShaderSource(GLuint shader, GLsizei count,
-    const GLchar** string, const GLint* length) {
-    ALOGD("const char* shaderSrc[] = {");
-    for (GLsizei i = 0; i < count; i++) {
-        const char* comma = i < count-1 ? "," : "";
-        const GLchar* s = string[i];
-        if (length) {
-            GLint len = length[i];
-            ALOGD("    \"%*s\"%s", len, s, comma);
-        } else {
-            ALOGD("    \"%s\"%s", s, comma);
-        }
-    }
-    ALOGD("};");
-    if (length) {
-        ALOGD("const GLint* shaderLength[] = {");
-        for (GLsizei i = 0; i < count; i++) {
-            const char* comma = i < count-1 ? "," : "";
-            GLint len = length[i];
-            ALOGD("    \"%d\"%s", len, comma);
-        }
-        ALOGD("};");
-        ALOGD("glShaderSource(%u, %u, shaderSrc, shaderLength);",
-            shader, count);
-    } else {
-        ALOGD("glShaderSource(%u, %u, shaderSrc, (const GLint*) 0);",
-            shader, count);
-    }
-}
-
-static void TraceValue(int elementCount, char type,
-        GLsizei chunkCount, GLsizei chunkSize, const void* value) {
-    StringBuilder stringBuilder;
-    GLsizei count = chunkCount * chunkSize;
-    bool isFloat = type == 'f';
-    const char* typeString = isFloat ? "GLfloat" : "GLint";
-    ALOGD("const %s value[] = {", typeString);
-    for (GLsizei i = 0; i < count; i++) {
-        StringBuilder builder;
-        builder.append("    ");
-        for (int e = 0; e < elementCount; e++) {
-            const char* comma = ", ";
-            if (e == elementCount-1) {
-                if (i == count - 1) {
-                    comma = "";
-                } else {
-                    comma = ",";
-                }
-            }
-            if (isFloat) {
-                builder.append("%g%s", * (GLfloat*) value, comma);
-                value = (void*) (((GLfloat*) value) + 1);
-            } else {
-                builder.append("%d%s", * (GLint*) value, comma);
-                value = (void*) (((GLint*) value) + 1);
-            }
-        }
-        ALOGD("%s", builder.getString());
-        if (chunkSize > 1 && i < count-1
-                && (i % chunkSize) == (chunkSize-1)) {
-            ALOGD("%s", ""); // Print a blank line.
-        }
-    }
-    ALOGD("};");
-}
-
-static void TraceUniformv(int elementCount, char type,
-        GLuint location, GLsizei count, const void* value) {
-    TraceValue(elementCount, type, count, 1, value);
-    ALOGD("glUniform%d%c(%u, %u, value);", elementCount, type, location, count);
-}
-
-static void TraceUniformMatrix(int matrixSideLength,
-        GLuint location, GLsizei count, GLboolean transpose, const void* value) {
-    TraceValue(matrixSideLength, 'f', count, matrixSideLength, value);
-    ALOGD("glUniformMatrix%dfv(%u, %u, %s, value);", matrixSideLength, location, count,
-            GLbooleanToString(transpose));
-}
-
-static void TraceGL(const char* name, int numArgs, ...) {
-    va_list argp;
-    va_start(argp, numArgs);
-    int nameLen = strlen(name);
-
-    // glShaderSource
-    if (nameLen == 14 && strcmp(name, "glShaderSource") == 0) {
-        va_arg(argp, const char*);
-        GLuint shader = va_arg(argp, GLuint);
-        va_arg(argp, const char*);
-        GLsizei count = va_arg(argp, GLsizei);
-        va_arg(argp, const char*);
-        const GLchar** string = (const GLchar**) va_arg(argp, void*);
-        va_arg(argp, const char*);
-        const GLint* length = (const GLint*) va_arg(argp, void*);
-        va_end(argp);
-        TraceGLShaderSource(shader, count, string, length);
-        return;
-    }
-
-    // glUniformXXv
-
-    if (nameLen == 12 && strncmp(name, "glUniform", 9) == 0 && name[11] == 'v') {
-        int elementCount = name[9] - '0'; // 1..4
-        char type = name[10]; // 'f' or 'i'
-        va_arg(argp, const char*);
-        GLuint location = va_arg(argp, GLuint);
-        va_arg(argp, const char*);
-        GLsizei count = va_arg(argp, GLsizei);
-        va_arg(argp, const char*);
-        const void* value = (const void*) va_arg(argp, void*);
-        va_end(argp);
-        TraceUniformv(elementCount, type, location, count, value);
-        return;
-    }
-
-    // glUniformMatrixXfv
-
-    if (nameLen == 18 && strncmp(name, "glUniformMatrix", 15) == 0
-            && name[16] == 'f' && name[17] == 'v') {
-        int matrixSideLength = name[15] - '0'; // 2..4
-        va_arg(argp, const char*);
-        GLuint location = va_arg(argp, GLuint);
-        va_arg(argp, const char*);
-        GLsizei count = va_arg(argp, GLsizei);
-        va_arg(argp, const char*);
-        GLboolean transpose = (GLboolean) va_arg(argp, int);
-        va_arg(argp, const char*);
-        const void* value = (const void*) va_arg(argp, void*);
-        va_end(argp);
-        TraceUniformMatrix(matrixSideLength, location, count, transpose, value);
-        return;
-    }
-
-    StringBuilder builder;
-    builder.append("%s(", name);
-    for (int i = 0; i < numArgs; i++) {
-        if (i > 0) {
-            builder.append(", ");
-        }
-        const char* type = va_arg(argp, const char*);
-        bool isPtr = type[strlen(type)-1] == '*'
-            || strcmp(type, "GLeglImageOES") == 0;
-        if (isPtr) {
-            const void* arg = va_arg(argp, const void*);
-            builder.append("(%s) 0x%08x", type, (size_t) arg);
-        } else if (strcmp(type, "GLbitfield") == 0) {
-            size_t arg = va_arg(argp, size_t);
-            bool first = true;
-            for (size_t i = 0; i < sizeof(g_bitfieldNames) / sizeof(g_bitfieldNames[0]); i++) {
-                const GLenumString* b = &g_bitfieldNames[i];
-                if (b->e & arg) {
-                    if (first) {
-                        first = false;
-                    } else {
-                        builder.append(" | ");
-                    }
-                    builder.append("%s", b->s);
-                    arg &= ~b->e;
-                }
-            }
-            if (first || arg != 0) {
-                if (!first) {
-                    builder.append(" | ");
-                }
-                builder.append("0x%08x", arg);
-            }
-        } else if (strcmp(type, "GLboolean") == 0) {
-            GLboolean arg = va_arg(argp, int);
-            builder.append("%s", GLbooleanToString(arg));
-        } else if (strcmp(type, "GLclampf") == 0) {
-            double arg = va_arg(argp, double);
-            builder.append("%g", arg);
-        } else if (strcmp(type, "GLenum") == 0) {
-            GLenum arg = va_arg(argp, int);
-            const char* s = GLEnumToString(arg);
-            if (s) {
-                builder.append("%s", s);
-            } else {
-                builder.append("0x%x", arg);
-            }
-        } else if (strcmp(type, "GLfixed") == 0) {
-            int arg = va_arg(argp, int);
-            builder.append("0x%08x", arg);
-        } else if (strcmp(type, "GLfloat") == 0) {
-            double arg = va_arg(argp, double);
-            builder.append("%g", arg);
-        } else if (strcmp(type, "GLint") == 0) {
-            int arg = va_arg(argp, int);
-            const char* s = NULL;
-            if (strcmp(name, "glTexParameteri") == 0) {
-                s = GLEnumToString(arg);
-            }
-            if (s) {
-                builder.append("%s", s);
-            } else {
-                builder.append("%d", arg);
-            }
-        } else if (strcmp(type, "GLintptr") == 0) {
-            int arg = va_arg(argp, unsigned int);
-            builder.append("%u", arg);
-        } else if (strcmp(type, "GLsizei") == 0) {
-            int arg = va_arg(argp, size_t);
-            builder.append("%u", arg);
-        } else if (strcmp(type, "GLsizeiptr") == 0) {
-            int arg = va_arg(argp, size_t);
-            builder.append("%u", arg);
-        } else if (strcmp(type, "GLuint") == 0) {
-            int arg = va_arg(argp, unsigned int);
-            builder.append("%u", arg);
-        } else {
-            builder.append("/* ??? %s */", type);
-            break;
-        }
-    }
-    builder.append(");");
-    ALOGD("%s", builder.getString());
-    va_end(argp);
-}
-
-///////////////////////////////////////////////////////////////////////////
-// Log trace
-///////////////////////////////////////////////////////////////////////////
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
-static void Tracing_ ## _api _args {                                      \
-    TraceGL(#_api, __VA_ARGS__);                                          \
-    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
-    _c->_api _argList;                                                    \
-}
-
-#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
-static _type Tracing_ ## _api _args {                                     \
-    TraceGL(#_api, __VA_ARGS__);                                        \
-    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
-    return _c->_api _argList;                                             \
-}
-
-extern "C" {
-#include "../trace.in"
-}
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-#define GL_ENTRY(_r, _api, ...) Tracing_ ## _api,
-EGLAPI gl_hooks_t gHooksTrace = {
-    {
-        #include "entries.in"
-    },
-    {
-        {0}
-    }
-};
-#undef GL_ENTRY
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-///////////////////////////////////////////////////////////////////////////
-// Systrace
-///////////////////////////////////////////////////////////////////////////
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
-static void Systrace_ ## _api _args {                                     \
-    ATRACE_NAME(#_api);                                                   \
-    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
-    _c->_api _argList;                                                    \
-}
-
-#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
-static _type Systrace_ ## _api _args {                                    \
-    ATRACE_NAME(#_api);                                                   \
-    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
-    return _c->_api _argList;                                             \
-}
-
-extern "C" {
-#include "../trace.in"
-}
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-#define GL_ENTRY(_r, _api, ...) Systrace_ ## _api,
-EGLAPI gl_hooks_t gHooksSystrace = {
-    {
-        #include "entries.in"
-    },
-    {
-        {0}
-    }
-};
-#undef GL_ENTRY
-
-///////////////////////////////////////////////////////////////////////////
-//
-///////////////////////////////////////////////////////////////////////////
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-#define CHECK_ERROR(_c, _api)                                             \
-    GLenum status = GL_NO_ERROR;                                          \
-    bool error = false;                                                   \
-    while ((status = _c->glGetError()) != GL_NO_ERROR) {                  \
-        ALOGD("[" #_api "] 0x%x", status);                                \
-        error = true;                                                     \
-    }                                                                     \
-    if (error) {                                                          \
-        CallStack s;                                                      \
-        s.update();                                                       \
-        s.log("glGetError:" #_api);                                       \
-    }                                                                     \
-
-#define TRACE_GL_VOID(_api, _args, _argList, ...)                         \
-static void ErrorTrace_ ## _api _args {                                   \
-    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
-    _c->_api _argList;                                                    \
-    CHECK_ERROR(_c, _api);                                                \
-}
-
-#define TRACE_GL(_type, _api, _args, _argList, ...)                       \
-static _type ErrorTrace_ ## _api _args {                                  \
-    gl_hooks_t::gl_t const * const _c = &getGLTraceThreadSpecific()->gl;  \
-    _type _r = _c->_api _argList;                                         \
-    CHECK_ERROR(_c, _api);                                                \
-    return _r;                                                            \
-}
-
-extern "C" {
-#include "../trace.in"
-}
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-#define GL_ENTRY(_r, _api, ...) ErrorTrace_ ## _api,
-EGLAPI gl_hooks_t gHooksErrorTrace = {
-    {
-        #include "entries.in"
-    },
-    {
-        {0}
-    }
-};
-#undef GL_ENTRY
-#undef CHECK_ERROR
-
-#undef TRACE_GL_VOID
-#undef TRACE_GL
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-// ----------------------------------------------------------------------------
-
-#endif // EGL_TRACE
diff --git a/opengl/libs/GLES2/gl2_api.in b/opengl/libs/GLES2/gl2_api.in
index 09d8b00..a331572 100644
--- a/opengl/libs/GLES2/gl2_api.in
+++ b/opengl/libs/GLES2/gl2_api.in
@@ -4,7 +4,7 @@
 void API_ENTRY(glAttachShader)(GLuint program, GLuint shader) {
     CALL_GL_API(glAttachShader, program, shader);
 }
-void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar * name) {
+void API_ENTRY(glBindAttribLocation)(GLuint program, GLuint index, const GLchar *name) {
     CALL_GL_API(glBindAttribLocation, program, index, name);
 }
 void API_ENTRY(glBindBuffer)(GLenum target, GLuint buffer) {
@@ -34,10 +34,10 @@
 void API_ENTRY(glBlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
     CALL_GL_API(glBlendFuncSeparate, sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
 }
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void * data, GLenum usage) {
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
     CALL_GL_API(glBufferData, target, size, data, usage);
 }
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data) {
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
     CALL_GL_API(glBufferSubData, target, offset, size, data);
 }
 GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target) {
@@ -61,10 +61,10 @@
 void API_ENTRY(glCompileShader)(GLuint shader) {
     CALL_GL_API(glCompileShader, shader);
 }
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
 }
-void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
 }
 void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
@@ -82,22 +82,22 @@
 void API_ENTRY(glCullFace)(GLenum mode) {
     CALL_GL_API(glCullFace, mode);
 }
-void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint * buffers) {
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint *buffers) {
     CALL_GL_API(glDeleteBuffers, n, buffers);
 }
-void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint * framebuffers) {
+void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers) {
     CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
 }
 void API_ENTRY(glDeleteProgram)(GLuint program) {
     CALL_GL_API(glDeleteProgram, program);
 }
-void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers) {
+void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint *renderbuffers) {
     CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
 }
 void API_ENTRY(glDeleteShader)(GLuint shader) {
     CALL_GL_API(glDeleteShader, shader);
 }
-void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint * textures) {
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
     CALL_GL_API(glDeleteTextures, n, textures);
 }
 void API_ENTRY(glDepthFunc)(GLenum func) {
@@ -121,7 +121,7 @@
 void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
     CALL_GL_API(glDrawArrays, mode, first, count);
 }
-void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void * indices) {
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void *indices) {
     CALL_GL_API(glDrawElements, mode, count, type, indices);
 }
 void API_ENTRY(glEnable)(GLenum cap) {
@@ -145,97 +145,97 @@
 void API_ENTRY(glFrontFace)(GLenum mode) {
     CALL_GL_API(glFrontFace, mode);
 }
-void API_ENTRY(glGenBuffers)(GLsizei n, GLuint * buffers) {
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint *buffers) {
     CALL_GL_API(glGenBuffers, n, buffers);
 }
 void API_ENTRY(glGenerateMipmap)(GLenum target) {
     CALL_GL_API(glGenerateMipmap, target);
 }
-void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint * framebuffers) {
+void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint *framebuffers) {
     CALL_GL_API(glGenFramebuffers, n, framebuffers);
 }
-void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint * renderbuffers) {
+void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint *renderbuffers) {
     CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
 }
-void API_ENTRY(glGenTextures)(GLsizei n, GLuint * textures) {
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
     CALL_GL_API(glGenTextures, n, textures);
 }
-void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) {
+void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
     CALL_GL_API(glGetActiveAttrib, program, index, bufSize, length, size, type, name);
 }
-void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) {
+void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
     CALL_GL_API(glGetActiveUniform, program, index, bufSize, length, size, type, name);
 }
-void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders) {
+void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) {
     CALL_GL_API(glGetAttachedShaders, program, maxCount, count, shaders);
 }
-GLint API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar * name) {
+GLint API_ENTRY(glGetAttribLocation)(GLuint program, const GLchar *name) {
     CALL_GL_API_RETURN(glGetAttribLocation, program, name);
 }
-void API_ENTRY(__glGetBooleanv)(GLenum pname, GLboolean * data) {
+void API_ENTRY(__glGetBooleanv)(GLenum pname, GLboolean *data) {
     CALL_GL_API(glGetBooleanv, pname, data);
 }
-void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetBufferParameteriv, target, pname, params);
 }
 GLenum API_ENTRY(glGetError)(void) {
     CALL_GL_API_RETURN(glGetError);
 }
-void API_ENTRY(__glGetFloatv)(GLenum pname, GLfloat * data) {
+void API_ENTRY(__glGetFloatv)(GLenum pname, GLfloat *data) {
     CALL_GL_API(glGetFloatv, pname, data);
 }
-void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params) {
+void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params) {
     CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
 }
-void API_ENTRY(__glGetIntegerv)(GLenum pname, GLint * data) {
+void API_ENTRY(__glGetIntegerv)(GLenum pname, GLint *data) {
     CALL_GL_API(glGetIntegerv, pname, data);
 }
-void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint * params) {
+void API_ENTRY(glGetProgramiv)(GLuint program, GLenum pname, GLint *params) {
     CALL_GL_API(glGetProgramiv, program, pname, params);
 }
-void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
+void API_ENTRY(glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
     CALL_GL_API(glGetProgramInfoLog, program, bufSize, length, infoLog);
 }
-void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
 }
-void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint * params) {
+void API_ENTRY(glGetShaderiv)(GLuint shader, GLenum pname, GLint *params) {
     CALL_GL_API(glGetShaderiv, shader, pname, params);
 }
-void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
+void API_ENTRY(glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
     CALL_GL_API(glGetShaderInfoLog, shader, bufSize, length, infoLog);
 }
-void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision) {
+void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision) {
     CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
 }
-void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source) {
+void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) {
     CALL_GL_API(glGetShaderSource, shader, bufSize, length, source);
 }
 const GLubyte * API_ENTRY(__glGetString)(GLenum name) {
     CALL_GL_API_RETURN(glGetString, name);
 }
-void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexParameterfv, target, pname, params);
 }
-void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexParameteriv, target, pname, params);
 }
-void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat * params) {
+void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat *params) {
     CALL_GL_API(glGetUniformfv, program, location, params);
 }
-void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint * params) {
+void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint *params) {
     CALL_GL_API(glGetUniformiv, program, location, params);
 }
-GLint API_ENTRY(glGetUniformLocation)(GLuint program, const GLchar * name) {
+GLint API_ENTRY(glGetUniformLocation)(GLuint program, const GLchar *name) {
     CALL_GL_API_RETURN(glGetUniformLocation, program, name);
 }
-void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetVertexAttribfv, index, pname, params);
 }
-void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint * params) {
+void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint *params) {
     CALL_GL_API(glGetVertexAttribiv, index, pname, params);
 }
-void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, void ** pointer) {
+void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, void **pointer) {
     CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
 }
 void API_ENTRY(glHint)(GLenum target, GLenum mode) {
@@ -274,7 +274,7 @@
 void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units) {
     CALL_GL_API(glPolygonOffset, factor, units);
 }
-void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels) {
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) {
     CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
 }
 void API_ENTRY(glReleaseShaderCompiler)(void) {
@@ -289,10 +289,10 @@
 void API_ENTRY(glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) {
     CALL_GL_API(glScissor, x, y, width, height);
 }
-void API_ENTRY(glShaderBinary)(GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length) {
+void API_ENTRY(glShaderBinary)(GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) {
     CALL_GL_API(glShaderBinary, count, shaders, binaryformat, binary, length);
 }
-void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length) {
+void API_ENTRY(glShaderSource)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) {
     CALL_GL_API(glShaderSource, shader, count, string, length);
 }
 void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask) {
@@ -313,79 +313,79 @@
 void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
     CALL_GL_API(glStencilOpSeparate, face, sfail, dpfail, dppass);
 }
-void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
 }
 void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
     CALL_GL_API(glTexParameterf, target, pname, param);
 }
-void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat * params) {
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
     CALL_GL_API(glTexParameterfv, target, pname, params);
 }
 void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glTexParameteri, target, pname, param);
 }
-void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint * params) {
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexParameteriv, target, pname, params);
 }
-void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
 }
 void API_ENTRY(glUniform1f)(GLint location, GLfloat v0) {
     CALL_GL_API(glUniform1f, location, v0);
 }
-void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glUniform1fv, location, count, value);
 }
 void API_ENTRY(glUniform1i)(GLint location, GLint v0) {
     CALL_GL_API(glUniform1i, location, v0);
 }
-void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glUniform1iv, location, count, value);
 }
 void API_ENTRY(glUniform2f)(GLint location, GLfloat v0, GLfloat v1) {
     CALL_GL_API(glUniform2f, location, v0, v1);
 }
-void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glUniform2fv, location, count, value);
 }
 void API_ENTRY(glUniform2i)(GLint location, GLint v0, GLint v1) {
     CALL_GL_API(glUniform2i, location, v0, v1);
 }
-void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glUniform2iv, location, count, value);
 }
 void API_ENTRY(glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
     CALL_GL_API(glUniform3f, location, v0, v1, v2);
 }
-void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glUniform3fv, location, count, value);
 }
 void API_ENTRY(glUniform3i)(GLint location, GLint v0, GLint v1, GLint v2) {
     CALL_GL_API(glUniform3i, location, v0, v1, v2);
 }
-void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glUniform3iv, location, count, value);
 }
 void API_ENTRY(glUniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
     CALL_GL_API(glUniform4f, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glUniform4fv, location, count, value);
 }
 void API_ENTRY(glUniform4i)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
     CALL_GL_API(glUniform4i, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glUniform4iv, location, count, value);
 }
-void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix4fv, location, count, transpose, value);
 }
 void API_ENTRY(glUseProgram)(GLuint program) {
@@ -397,58 +397,58 @@
 void API_ENTRY(glVertexAttrib1f)(GLuint index, GLfloat x) {
     CALL_GL_API(glVertexAttrib1f, index, x);
 }
-void API_ENTRY(glVertexAttrib1fv)(GLuint index, const GLfloat * v) {
+void API_ENTRY(glVertexAttrib1fv)(GLuint index, const GLfloat *v) {
     CALL_GL_API(glVertexAttrib1fv, index, v);
 }
 void API_ENTRY(glVertexAttrib2f)(GLuint index, GLfloat x, GLfloat y) {
     CALL_GL_API(glVertexAttrib2f, index, x, y);
 }
-void API_ENTRY(glVertexAttrib2fv)(GLuint index, const GLfloat * v) {
+void API_ENTRY(glVertexAttrib2fv)(GLuint index, const GLfloat *v) {
     CALL_GL_API(glVertexAttrib2fv, index, v);
 }
 void API_ENTRY(glVertexAttrib3f)(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
     CALL_GL_API(glVertexAttrib3f, index, x, y, z);
 }
-void API_ENTRY(glVertexAttrib3fv)(GLuint index, const GLfloat * v) {
+void API_ENTRY(glVertexAttrib3fv)(GLuint index, const GLfloat *v) {
     CALL_GL_API(glVertexAttrib3fv, index, v);
 }
 void API_ENTRY(glVertexAttrib4f)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
     CALL_GL_API(glVertexAttrib4f, index, x, y, z, w);
 }
-void API_ENTRY(glVertexAttrib4fv)(GLuint index, const GLfloat * v) {
+void API_ENTRY(glVertexAttrib4fv)(GLuint index, const GLfloat *v) {
     CALL_GL_API(glVertexAttrib4fv, index, v);
 }
-void API_ENTRY(glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer) {
+void API_ENTRY(glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {
     CALL_GL_API(glVertexAttribPointer, index, size, type, normalized, stride, pointer);
 }
 void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
     CALL_GL_API(glViewport, x, y, width, height);
 }
-void API_ENTRY(glReadBuffer)(GLenum mode) {
-    CALL_GL_API(glReadBuffer, mode);
+void API_ENTRY(glReadBuffer)(GLenum src) {
+    CALL_GL_API(glReadBuffer, src);
 }
-void API_ENTRY(glDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices) {
+void API_ENTRY(glDrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) {
     CALL_GL_API(glDrawRangeElements, mode, start, end, count, type, indices);
 }
-void API_ENTRY(glTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexImage3D, target, level, internalformat, width, height, depth, border, format, type, pixels);
 }
-void API_ENTRY(glTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexSubImage3D, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
 }
 void API_ENTRY(glCopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
     CALL_GL_API(glCopyTexSubImage3D, target, level, xoffset, yoffset, zoffset, x, y, width, height);
 }
-void API_ENTRY(glCompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexImage3D, target, level, internalformat, width, height, depth, border, imageSize, data);
 }
-void API_ENTRY(glCompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexSubImage3D, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
 }
-void API_ENTRY(glGenQueries)(GLsizei n, GLuint * ids) {
+void API_ENTRY(glGenQueries)(GLsizei n, GLuint *ids) {
     CALL_GL_API(glGenQueries, n, ids);
 }
-void API_ENTRY(glDeleteQueries)(GLsizei n, const GLuint * ids) {
+void API_ENTRY(glDeleteQueries)(GLsizei n, const GLuint *ids) {
     CALL_GL_API(glDeleteQueries, n, ids);
 }
 GLboolean API_ENTRY(glIsQuery)(GLuint id) {
@@ -460,37 +460,37 @@
 void API_ENTRY(glEndQuery)(GLenum target) {
     CALL_GL_API(glEndQuery, target);
 }
-void API_ENTRY(glGetQueryiv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetQueryiv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetQueryiv, target, pname, params);
 }
-void API_ENTRY(glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint * params) {
+void API_ENTRY(glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params) {
     CALL_GL_API(glGetQueryObjectuiv, id, pname, params);
 }
 GLboolean API_ENTRY(glUnmapBuffer)(GLenum target) {
     CALL_GL_API_RETURN(glUnmapBuffer, target);
 }
-void API_ENTRY(glGetBufferPointerv)(GLenum target, GLenum pname, void ** params) {
+void API_ENTRY(glGetBufferPointerv)(GLenum target, GLenum pname, void **params) {
     CALL_GL_API(glGetBufferPointerv, target, pname, params);
 }
-void API_ENTRY(glDrawBuffers)(GLsizei n, const GLenum * bufs) {
+void API_ENTRY(glDrawBuffers)(GLsizei n, const GLenum *bufs) {
     CALL_GL_API(glDrawBuffers, n, bufs);
 }
-void API_ENTRY(glUniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix2x3fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix3x2fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix2x4fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix4x2fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix3x4fv, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix4x3fv, location, count, transpose, value);
 }
 void API_ENTRY(glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
@@ -511,16 +511,16 @@
 void API_ENTRY(glBindVertexArray)(GLuint array) {
     CALL_GL_API(glBindVertexArray, array);
 }
-void API_ENTRY(glDeleteVertexArrays)(GLsizei n, const GLuint * arrays) {
+void API_ENTRY(glDeleteVertexArrays)(GLsizei n, const GLuint *arrays) {
     CALL_GL_API(glDeleteVertexArrays, n, arrays);
 }
-void API_ENTRY(glGenVertexArrays)(GLsizei n, GLuint * arrays) {
+void API_ENTRY(glGenVertexArrays)(GLsizei n, GLuint *arrays) {
     CALL_GL_API(glGenVertexArrays, n, arrays);
 }
 GLboolean API_ENTRY(glIsVertexArray)(GLuint array) {
     CALL_GL_API_RETURN(glIsVertexArray, array);
 }
-void API_ENTRY(glGetIntegeri_v)(GLenum target, GLuint index, GLint * data) {
+void API_ENTRY(glGetIntegeri_v)(GLenum target, GLuint index, GLint *data) {
     CALL_GL_API(glGetIntegeri_v, target, index, data);
 }
 void API_ENTRY(glBeginTransformFeedback)(GLenum primitiveMode) {
@@ -535,19 +535,19 @@
 void API_ENTRY(glBindBufferBase)(GLenum target, GLuint index, GLuint buffer) {
     CALL_GL_API(glBindBufferBase, target, index, buffer);
 }
-void API_ENTRY(glTransformFeedbackVaryings)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode) {
+void API_ENTRY(glTransformFeedbackVaryings)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode) {
     CALL_GL_API(glTransformFeedbackVaryings, program, count, varyings, bufferMode);
 }
-void API_ENTRY(glGetTransformFeedbackVarying)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name) {
+void API_ENTRY(glGetTransformFeedbackVarying)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) {
     CALL_GL_API(glGetTransformFeedbackVarying, program, index, bufSize, length, size, type, name);
 }
-void API_ENTRY(glVertexAttribIPointer)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glVertexAttribIPointer)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glVertexAttribIPointer, index, size, type, stride, pointer);
 }
-void API_ENTRY(glGetVertexAttribIiv)(GLuint index, GLenum pname, GLint * params) {
+void API_ENTRY(glGetVertexAttribIiv)(GLuint index, GLenum pname, GLint *params) {
     CALL_GL_API(glGetVertexAttribIiv, index, pname, params);
 }
-void API_ENTRY(glGetVertexAttribIuiv)(GLuint index, GLenum pname, GLuint * params) {
+void API_ENTRY(glGetVertexAttribIuiv)(GLuint index, GLenum pname, GLuint *params) {
     CALL_GL_API(glGetVertexAttribIuiv, index, pname, params);
 }
 void API_ENTRY(glVertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w) {
@@ -556,16 +556,16 @@
 void API_ENTRY(glVertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {
     CALL_GL_API(glVertexAttribI4ui, index, x, y, z, w);
 }
-void API_ENTRY(glVertexAttribI4iv)(GLuint index, const GLint * v) {
+void API_ENTRY(glVertexAttribI4iv)(GLuint index, const GLint *v) {
     CALL_GL_API(glVertexAttribI4iv, index, v);
 }
-void API_ENTRY(glVertexAttribI4uiv)(GLuint index, const GLuint * v) {
+void API_ENTRY(glVertexAttribI4uiv)(GLuint index, const GLuint *v) {
     CALL_GL_API(glVertexAttribI4uiv, index, v);
 }
-void API_ENTRY(glGetUniformuiv)(GLuint program, GLint location, GLuint * params) {
+void API_ENTRY(glGetUniformuiv)(GLuint program, GLint location, GLuint *params) {
     CALL_GL_API(glGetUniformuiv, program, location, params);
 }
-GLint API_ENTRY(glGetFragDataLocation)(GLuint program, const GLchar * name) {
+GLint API_ENTRY(glGetFragDataLocation)(GLuint program, const GLchar *name) {
     CALL_GL_API_RETURN(glGetFragDataLocation, program, name);
 }
 void API_ENTRY(glUniform1ui)(GLint location, GLuint v0) {
@@ -580,25 +580,25 @@
 void API_ENTRY(glUniform4ui)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
     CALL_GL_API(glUniform4ui, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glUniform1uiv)(GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glUniform1uiv)(GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glUniform1uiv, location, count, value);
 }
-void API_ENTRY(glUniform2uiv)(GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glUniform2uiv)(GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glUniform2uiv, location, count, value);
 }
-void API_ENTRY(glUniform3uiv)(GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glUniform3uiv)(GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glUniform3uiv, location, count, value);
 }
-void API_ENTRY(glUniform4uiv)(GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glUniform4uiv)(GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glUniform4uiv, location, count, value);
 }
-void API_ENTRY(glClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint * value) {
+void API_ENTRY(glClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint *value) {
     CALL_GL_API(glClearBufferiv, buffer, drawbuffer, value);
 }
-void API_ENTRY(glClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint * value) {
+void API_ENTRY(glClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint *value) {
     CALL_GL_API(glClearBufferuiv, buffer, drawbuffer, value);
 }
-void API_ENTRY(glClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat * value) {
+void API_ENTRY(glClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat *value) {
     CALL_GL_API(glClearBufferfv, buffer, drawbuffer, value);
 }
 void API_ENTRY(glClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
@@ -610,19 +610,19 @@
 void API_ENTRY(glCopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
     CALL_GL_API(glCopyBufferSubData, readTarget, writeTarget, readOffset, writeOffset, size);
 }
-void API_ENTRY(glGetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices) {
+void API_ENTRY(glGetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices) {
     CALL_GL_API(glGetUniformIndices, program, uniformCount, uniformNames, uniformIndices);
 }
-void API_ENTRY(glGetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params) {
+void API_ENTRY(glGetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params) {
     CALL_GL_API(glGetActiveUniformsiv, program, uniformCount, uniformIndices, pname, params);
 }
-GLuint API_ENTRY(glGetUniformBlockIndex)(GLuint program, const GLchar * uniformBlockName) {
+GLuint API_ENTRY(glGetUniformBlockIndex)(GLuint program, const GLchar *uniformBlockName) {
     CALL_GL_API_RETURN(glGetUniformBlockIndex, program, uniformBlockName);
 }
-void API_ENTRY(glGetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params) {
+void API_ENTRY(glGetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params) {
     CALL_GL_API(glGetActiveUniformBlockiv, program, uniformBlockIndex, pname, params);
 }
-void API_ENTRY(glGetActiveUniformBlockName)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName) {
+void API_ENTRY(glGetActiveUniformBlockName)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) {
     CALL_GL_API(glGetActiveUniformBlockName, program, uniformBlockIndex, bufSize, length, uniformBlockName);
 }
 void API_ENTRY(glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) {
@@ -631,7 +631,7 @@
 void API_ENTRY(glDrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
     CALL_GL_API(glDrawArraysInstanced, mode, first, count, instancecount);
 }
-void API_ENTRY(glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount) {
+void API_ENTRY(glDrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount) {
     CALL_GL_API(glDrawElementsInstanced, mode, count, type, indices, instancecount);
 }
 GLsync API_ENTRY(glFenceSync)(GLenum condition, GLbitfield flags) {
@@ -649,22 +649,22 @@
 void API_ENTRY(glWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout) {
     CALL_GL_API(glWaitSync, sync, flags, timeout);
 }
-void API_ENTRY(__glGetInteger64v)(GLenum pname, GLint64 * data) {
+void API_ENTRY(__glGetInteger64v)(GLenum pname, GLint64 *data) {
     CALL_GL_API(glGetInteger64v, pname, data);
 }
-void API_ENTRY(glGetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) {
+void API_ENTRY(glGetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
     CALL_GL_API(glGetSynciv, sync, pname, bufSize, length, values);
 }
-void API_ENTRY(glGetInteger64i_v)(GLenum target, GLuint index, GLint64 * data) {
+void API_ENTRY(glGetInteger64i_v)(GLenum target, GLuint index, GLint64 *data) {
     CALL_GL_API(glGetInteger64i_v, target, index, data);
 }
-void API_ENTRY(glGetBufferParameteri64v)(GLenum target, GLenum pname, GLint64 * params) {
+void API_ENTRY(glGetBufferParameteri64v)(GLenum target, GLenum pname, GLint64 *params) {
     CALL_GL_API(glGetBufferParameteri64v, target, pname, params);
 }
-void API_ENTRY(glGenSamplers)(GLsizei count, GLuint * samplers) {
+void API_ENTRY(glGenSamplers)(GLsizei count, GLuint *samplers) {
     CALL_GL_API(glGenSamplers, count, samplers);
 }
-void API_ENTRY(glDeleteSamplers)(GLsizei count, const GLuint * samplers) {
+void API_ENTRY(glDeleteSamplers)(GLsizei count, const GLuint *samplers) {
     CALL_GL_API(glDeleteSamplers, count, samplers);
 }
 GLboolean API_ENTRY(glIsSampler)(GLuint sampler) {
@@ -676,19 +676,19 @@
 void API_ENTRY(glSamplerParameteri)(GLuint sampler, GLenum pname, GLint param) {
     CALL_GL_API(glSamplerParameteri, sampler, pname, param);
 }
-void API_ENTRY(glSamplerParameteriv)(GLuint sampler, GLenum pname, const GLint * param) {
+void API_ENTRY(glSamplerParameteriv)(GLuint sampler, GLenum pname, const GLint *param) {
     CALL_GL_API(glSamplerParameteriv, sampler, pname, param);
 }
 void API_ENTRY(glSamplerParameterf)(GLuint sampler, GLenum pname, GLfloat param) {
     CALL_GL_API(glSamplerParameterf, sampler, pname, param);
 }
-void API_ENTRY(glSamplerParameterfv)(GLuint sampler, GLenum pname, const GLfloat * param) {
+void API_ENTRY(glSamplerParameterfv)(GLuint sampler, GLenum pname, const GLfloat *param) {
     CALL_GL_API(glSamplerParameterfv, sampler, pname, param);
 }
-void API_ENTRY(glGetSamplerParameteriv)(GLuint sampler, GLenum pname, GLint * params) {
+void API_ENTRY(glGetSamplerParameteriv)(GLuint sampler, GLenum pname, GLint *params) {
     CALL_GL_API(glGetSamplerParameteriv, sampler, pname, params);
 }
-void API_ENTRY(glGetSamplerParameterfv)(GLuint sampler, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetSamplerParameterfv)(GLuint sampler, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetSamplerParameterfv, sampler, pname, params);
 }
 void API_ENTRY(glVertexAttribDivisor)(GLuint index, GLuint divisor) {
@@ -697,10 +697,10 @@
 void API_ENTRY(glBindTransformFeedback)(GLenum target, GLuint id) {
     CALL_GL_API(glBindTransformFeedback, target, id);
 }
-void API_ENTRY(glDeleteTransformFeedbacks)(GLsizei n, const GLuint * ids) {
+void API_ENTRY(glDeleteTransformFeedbacks)(GLsizei n, const GLuint *ids) {
     CALL_GL_API(glDeleteTransformFeedbacks, n, ids);
 }
-void API_ENTRY(glGenTransformFeedbacks)(GLsizei n, GLuint * ids) {
+void API_ENTRY(glGenTransformFeedbacks)(GLsizei n, GLuint *ids) {
     CALL_GL_API(glGenTransformFeedbacks, n, ids);
 }
 GLboolean API_ENTRY(glIsTransformFeedback)(GLuint id) {
@@ -712,19 +712,19 @@
 void API_ENTRY(glResumeTransformFeedback)(void) {
     CALL_GL_API(glResumeTransformFeedback);
 }
-void API_ENTRY(glGetProgramBinary)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary) {
+void API_ENTRY(glGetProgramBinary)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
     CALL_GL_API(glGetProgramBinary, program, bufSize, length, binaryFormat, binary);
 }
-void API_ENTRY(glProgramBinary)(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length) {
+void API_ENTRY(glProgramBinary)(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length) {
     CALL_GL_API(glProgramBinary, program, binaryFormat, binary, length);
 }
 void API_ENTRY(glProgramParameteri)(GLuint program, GLenum pname, GLint value) {
     CALL_GL_API(glProgramParameteri, program, pname, value);
 }
-void API_ENTRY(glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum * attachments) {
+void API_ENTRY(glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
     CALL_GL_API(glInvalidateFramebuffer, target, numAttachments, attachments);
 }
-void API_ENTRY(glInvalidateSubFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
+void API_ENTRY(glInvalidateSubFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
     CALL_GL_API(glInvalidateSubFramebuffer, target, numAttachments, attachments, x, y, width, height);
 }
 void API_ENTRY(glTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
@@ -733,7 +733,7 @@
 void API_ENTRY(glTexStorage3D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
     CALL_GL_API(glTexStorage3D, target, levels, internalformat, width, height, depth);
 }
-void API_ENTRY(glGetInternalformativ)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params) {
+void API_ENTRY(glGetInternalformativ)(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params) {
     CALL_GL_API(glGetInternalformativ, target, internalformat, pname, bufSize, params);
 }
 void API_ENTRY(glDispatchCompute)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
@@ -742,31 +742,31 @@
 void API_ENTRY(glDispatchComputeIndirect)(GLintptr indirect) {
     CALL_GL_API(glDispatchComputeIndirect, indirect);
 }
-void API_ENTRY(glDrawArraysIndirect)(GLenum mode, const void * indirect) {
+void API_ENTRY(glDrawArraysIndirect)(GLenum mode, const void *indirect) {
     CALL_GL_API(glDrawArraysIndirect, mode, indirect);
 }
-void API_ENTRY(glDrawElementsIndirect)(GLenum mode, GLenum type, const void * indirect) {
+void API_ENTRY(glDrawElementsIndirect)(GLenum mode, GLenum type, const void *indirect) {
     CALL_GL_API(glDrawElementsIndirect, mode, type, indirect);
 }
 void API_ENTRY(glFramebufferParameteri)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glFramebufferParameteri, target, pname, param);
 }
-void API_ENTRY(glGetFramebufferParameteriv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetFramebufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetFramebufferParameteriv, target, pname, params);
 }
-void API_ENTRY(glGetProgramInterfaceiv)(GLuint program, GLenum programInterface, GLenum pname, GLint * params) {
+void API_ENTRY(glGetProgramInterfaceiv)(GLuint program, GLenum programInterface, GLenum pname, GLint *params) {
     CALL_GL_API(glGetProgramInterfaceiv, program, programInterface, pname, params);
 }
-GLuint API_ENTRY(glGetProgramResourceIndex)(GLuint program, GLenum programInterface, const GLchar * name) {
+GLuint API_ENTRY(glGetProgramResourceIndex)(GLuint program, GLenum programInterface, const GLchar *name) {
     CALL_GL_API_RETURN(glGetProgramResourceIndex, program, programInterface, name);
 }
-void API_ENTRY(glGetProgramResourceName)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name) {
+void API_ENTRY(glGetProgramResourceName)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) {
     CALL_GL_API(glGetProgramResourceName, program, programInterface, index, bufSize, length, name);
 }
-void API_ENTRY(glGetProgramResourceiv)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
+void API_ENTRY(glGetProgramResourceiv)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params) {
     CALL_GL_API(glGetProgramResourceiv, program, programInterface, index, propCount, props, bufSize, length, params);
 }
-GLint API_ENTRY(glGetProgramResourceLocation)(GLuint program, GLenum programInterface, const GLchar * name) {
+GLint API_ENTRY(glGetProgramResourceLocation)(GLuint program, GLenum programInterface, const GLchar *name) {
     CALL_GL_API_RETURN(glGetProgramResourceLocation, program, programInterface, name);
 }
 void API_ENTRY(glUseProgramStages)(GLuint pipeline, GLbitfield stages, GLuint program) {
@@ -775,22 +775,22 @@
 void API_ENTRY(glActiveShaderProgram)(GLuint pipeline, GLuint program) {
     CALL_GL_API(glActiveShaderProgram, pipeline, program);
 }
-GLuint API_ENTRY(glCreateShaderProgramv)(GLenum type, GLsizei count, const GLchar *const* strings) {
+GLuint API_ENTRY(glCreateShaderProgramv)(GLenum type, GLsizei count, const GLchar *const*strings) {
     CALL_GL_API_RETURN(glCreateShaderProgramv, type, count, strings);
 }
 void API_ENTRY(glBindProgramPipeline)(GLuint pipeline) {
     CALL_GL_API(glBindProgramPipeline, pipeline);
 }
-void API_ENTRY(glDeleteProgramPipelines)(GLsizei n, const GLuint * pipelines) {
+void API_ENTRY(glDeleteProgramPipelines)(GLsizei n, const GLuint *pipelines) {
     CALL_GL_API(glDeleteProgramPipelines, n, pipelines);
 }
-void API_ENTRY(glGenProgramPipelines)(GLsizei n, GLuint * pipelines) {
+void API_ENTRY(glGenProgramPipelines)(GLsizei n, GLuint *pipelines) {
     CALL_GL_API(glGenProgramPipelines, n, pipelines);
 }
 GLboolean API_ENTRY(glIsProgramPipeline)(GLuint pipeline) {
     CALL_GL_API_RETURN(glIsProgramPipeline, pipeline);
 }
-void API_ENTRY(glGetProgramPipelineiv)(GLuint pipeline, GLenum pname, GLint * params) {
+void API_ENTRY(glGetProgramPipelineiv)(GLuint pipeline, GLenum pname, GLint *params) {
     CALL_GL_API(glGetProgramPipelineiv, pipeline, pname, params);
 }
 void API_ENTRY(glProgramUniform1i)(GLuint program, GLint location, GLint v0) {
@@ -829,79 +829,79 @@
 void API_ENTRY(glProgramUniform4f)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
     CALL_GL_API(glProgramUniform4f, program, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glProgramUniform1iv)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform1iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform1iv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform2iv)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform2iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform2iv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform3iv)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform3iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform3iv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform4iv)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform4iv)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform4iv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform1uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform1uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform1uiv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform2uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform2uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform2uiv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform3uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform3uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform3uiv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform4uiv)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform4uiv)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform4uiv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform1fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform1fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform1fv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform2fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform2fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform2fv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform3fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform3fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform3fv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform4fv)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform4fv)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform4fv, program, location, count, value);
 }
-void API_ENTRY(glProgramUniformMatrix2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix2fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix3fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix4fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix2x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix2x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix2x3fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix3x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix3x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix3x2fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix2x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix2x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix2x4fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix4x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix4x2fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix4x2fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix3x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix3x4fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix3x4fv, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix4x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix4x3fv)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix4x3fv, program, location, count, transpose, value);
 }
 void API_ENTRY(glValidateProgramPipeline)(GLuint pipeline) {
     CALL_GL_API(glValidateProgramPipeline, pipeline);
 }
-void API_ENTRY(glGetProgramPipelineInfoLog)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
+void API_ENTRY(glGetProgramPipelineInfoLog)(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
     CALL_GL_API(glGetProgramPipelineInfoLog, pipeline, bufSize, length, infoLog);
 }
 void API_ENTRY(glBindImageTexture)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) {
     CALL_GL_API(glBindImageTexture, unit, texture, level, layered, layer, access, format);
 }
-void API_ENTRY(glGetBooleani_v)(GLenum target, GLuint index, GLboolean * data) {
+void API_ENTRY(glGetBooleani_v)(GLenum target, GLuint index, GLboolean *data) {
     CALL_GL_API(glGetBooleani_v, target, index, data);
 }
 void API_ENTRY(glMemoryBarrier)(GLbitfield barriers) {
@@ -913,16 +913,16 @@
 void API_ENTRY(glTexStorage2DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
     CALL_GL_API(glTexStorage2DMultisample, target, samples, internalformat, width, height, fixedsamplelocations);
 }
-void API_ENTRY(glGetMultisamplefv)(GLenum pname, GLuint index, GLfloat * val) {
+void API_ENTRY(glGetMultisamplefv)(GLenum pname, GLuint index, GLfloat *val) {
     CALL_GL_API(glGetMultisamplefv, pname, index, val);
 }
 void API_ENTRY(glSampleMaski)(GLuint maskNumber, GLbitfield mask) {
     CALL_GL_API(glSampleMaski, maskNumber, mask);
 }
-void API_ENTRY(glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint * params) {
+void API_ENTRY(glGetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexLevelParameteriv, target, level, pname, params);
 }
-void API_ENTRY(glGetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexLevelParameterfv, target, level, pname, params);
 }
 void API_ENTRY(glBindVertexBuffer)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) {
@@ -940,3 +940,135 @@
 void API_ENTRY(glVertexBindingDivisor)(GLuint bindingindex, GLuint divisor) {
     CALL_GL_API(glVertexBindingDivisor, bindingindex, divisor);
 }
+void API_ENTRY(glBlendBarrier)(void) {
+    CALL_GL_API(glBlendBarrier);
+}
+void API_ENTRY(glCopyImageSubData)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
+    CALL_GL_API(glCopyImageSubData, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
+}
+void API_ENTRY(glDebugMessageControl)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled) {
+    CALL_GL_API(glDebugMessageControl, source, type, severity, count, ids, enabled);
+}
+void API_ENTRY(glDebugMessageInsert)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf) {
+    CALL_GL_API(glDebugMessageInsert, source, type, id, severity, length, buf);
+}
+void API_ENTRY(glDebugMessageCallback)(GLDEBUGPROC callback, const void *userParam) {
+    CALL_GL_API(glDebugMessageCallback, callback, userParam);
+}
+GLuint API_ENTRY(glGetDebugMessageLog)(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog) {
+    CALL_GL_API_RETURN(glGetDebugMessageLog, count, bufSize, sources, types, ids, severities, lengths, messageLog);
+}
+void API_ENTRY(glPushDebugGroup)(GLenum source, GLuint id, GLsizei length, const GLchar *message) {
+    CALL_GL_API(glPushDebugGroup, source, id, length, message);
+}
+void API_ENTRY(glPopDebugGroup)(void) {
+    CALL_GL_API(glPopDebugGroup);
+}
+void API_ENTRY(glObjectLabel)(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) {
+    CALL_GL_API(glObjectLabel, identifier, name, length, label);
+}
+void API_ENTRY(glGetObjectLabel)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label) {
+    CALL_GL_API(glGetObjectLabel, identifier, name, bufSize, length, label);
+}
+void API_ENTRY(glObjectPtrLabel)(const void *ptr, GLsizei length, const GLchar *label) {
+    CALL_GL_API(glObjectPtrLabel, ptr, length, label);
+}
+void API_ENTRY(glGetObjectPtrLabel)(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) {
+    CALL_GL_API(glGetObjectPtrLabel, ptr, bufSize, length, label);
+}
+void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
+    CALL_GL_API(glGetPointerv, pname, params);
+}
+void API_ENTRY(glEnablei)(GLenum target, GLuint index) {
+    CALL_GL_API(glEnablei, target, index);
+}
+void API_ENTRY(glDisablei)(GLenum target, GLuint index) {
+    CALL_GL_API(glDisablei, target, index);
+}
+void API_ENTRY(glBlendEquationi)(GLuint buf, GLenum mode) {
+    CALL_GL_API(glBlendEquationi, buf, mode);
+}
+void API_ENTRY(glBlendEquationSeparatei)(GLuint buf, GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparatei, buf, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunci)(GLuint buf, GLenum src, GLenum dst) {
+    CALL_GL_API(glBlendFunci, buf, src, dst);
+}
+void API_ENTRY(glBlendFuncSeparatei)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glColorMaski)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
+    CALL_GL_API(glColorMaski, index, r, g, b, a);
+}
+GLboolean API_ENTRY(glIsEnabledi)(GLenum target, GLuint index) {
+    CALL_GL_API_RETURN(glIsEnabledi, target, index);
+}
+void API_ENTRY(glDrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+    CALL_GL_API(glDrawElementsBaseVertex, mode, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawRangeElementsBaseVertex)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+    CALL_GL_API(glDrawRangeElementsBaseVertex, mode, start, end, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
+    CALL_GL_API(glDrawElementsInstancedBaseVertex, mode, count, type, indices, instancecount, basevertex);
+}
+void API_ENTRY(glFramebufferTexture)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTexture, target, attachment, texture, level);
+}
+void API_ENTRY(glPrimitiveBoundingBox)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
+    CALL_GL_API(glPrimitiveBoundingBox, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
+}
+GLenum API_ENTRY(glGetGraphicsResetStatus)(void) {
+    CALL_GL_API_RETURN(glGetGraphicsResetStatus);
+}
+void API_ENTRY(glReadnPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
+    CALL_GL_API(glReadnPixels, x, y, width, height, format, type, bufSize, data);
+}
+void API_ENTRY(glGetnUniformfv)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
+    CALL_GL_API(glGetnUniformfv, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformiv)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
+    CALL_GL_API(glGetnUniformiv, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformuiv)(GLuint program, GLint location, GLsizei bufSize, GLuint *params) {
+    CALL_GL_API(glGetnUniformuiv, program, location, bufSize, params);
+}
+void API_ENTRY(glMinSampleShading)(GLfloat value) {
+    CALL_GL_API(glMinSampleShading, value);
+}
+void API_ENTRY(glPatchParameteri)(GLenum pname, GLint value) {
+    CALL_GL_API(glPatchParameteri, pname, value);
+}
+void API_ENTRY(glTexParameterIiv)(GLenum target, GLenum pname, const GLint *params) {
+    CALL_GL_API(glTexParameterIiv, target, pname, params);
+}
+void API_ENTRY(glTexParameterIuiv)(GLenum target, GLenum pname, const GLuint *params) {
+    CALL_GL_API(glTexParameterIuiv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIiv)(GLenum target, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetTexParameterIiv, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIuiv)(GLenum target, GLenum pname, GLuint *params) {
+    CALL_GL_API(glGetTexParameterIuiv, target, pname, params);
+}
+void API_ENTRY(glSamplerParameterIiv)(GLuint sampler, GLenum pname, const GLint *param) {
+    CALL_GL_API(glSamplerParameterIiv, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterIuiv)(GLuint sampler, GLenum pname, const GLuint *param) {
+    CALL_GL_API(glSamplerParameterIuiv, sampler, pname, param);
+}
+void API_ENTRY(glGetSamplerParameterIiv)(GLuint sampler, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetSamplerParameterIiv, sampler, pname, params);
+}
+void API_ENTRY(glGetSamplerParameterIuiv)(GLuint sampler, GLenum pname, GLuint *params) {
+    CALL_GL_API(glGetSamplerParameterIuiv, sampler, pname, params);
+}
+void API_ENTRY(glTexBuffer)(GLenum target, GLenum internalformat, GLuint buffer) {
+    CALL_GL_API(glTexBuffer, target, internalformat, buffer);
+}
+void API_ENTRY(glTexBufferRange)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) {
+    CALL_GL_API(glTexBufferRange, target, internalformat, buffer, offset, size);
+}
+void API_ENTRY(glTexStorage3DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
+    CALL_GL_API(glTexStorage3DMultisample, target, samples, internalformat, width, height, depth, fixedsamplelocations);
+}
diff --git a/opengl/libs/GLES2/gl2ext_api.in b/opengl/libs/GLES2/gl2ext_api.in
index 745590d..fc368f2 100644
--- a/opengl/libs/GLES2/gl2ext_api.in
+++ b/opengl/libs/GLES2/gl2ext_api.in
@@ -1,49 +1,106 @@
 void API_ENTRY(glBlendBarrierKHR)(void) {
     CALL_GL_API(glBlendBarrierKHR);
 }
-void API_ENTRY(glDebugMessageControlKHR)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled) {
+void API_ENTRY(glDebugMessageControlKHR)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled) {
     CALL_GL_API(glDebugMessageControlKHR, source, type, severity, count, ids, enabled);
 }
-void API_ENTRY(glDebugMessageInsertKHR)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf) {
+void API_ENTRY(glDebugMessageInsertKHR)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf) {
     CALL_GL_API(glDebugMessageInsertKHR, source, type, id, severity, length, buf);
 }
-void API_ENTRY(glDebugMessageCallbackKHR)(GLDEBUGPROCKHR callback, const void * userParam) {
+void API_ENTRY(glDebugMessageCallbackKHR)(GLDEBUGPROCKHR callback, const void *userParam) {
     CALL_GL_API(glDebugMessageCallbackKHR, callback, userParam);
 }
-GLuint API_ENTRY(glGetDebugMessageLogKHR)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog) {
+GLuint API_ENTRY(glGetDebugMessageLogKHR)(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog) {
     CALL_GL_API_RETURN(glGetDebugMessageLogKHR, count, bufSize, sources, types, ids, severities, lengths, messageLog);
 }
-void API_ENTRY(glPushDebugGroupKHR)(GLenum source, GLuint id, GLsizei length, const GLchar * message) {
+void API_ENTRY(glPushDebugGroupKHR)(GLenum source, GLuint id, GLsizei length, const GLchar *message) {
     CALL_GL_API(glPushDebugGroupKHR, source, id, length, message);
 }
 void API_ENTRY(glPopDebugGroupKHR)(void) {
     CALL_GL_API(glPopDebugGroupKHR);
 }
-void API_ENTRY(glObjectLabelKHR)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label) {
+void API_ENTRY(glObjectLabelKHR)(GLenum identifier, GLuint name, GLsizei length, const GLchar *label) {
     CALL_GL_API(glObjectLabelKHR, identifier, name, length, label);
 }
-void API_ENTRY(glGetObjectLabelKHR)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label) {
+void API_ENTRY(glGetObjectLabelKHR)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label) {
     CALL_GL_API(glGetObjectLabelKHR, identifier, name, bufSize, length, label);
 }
-void API_ENTRY(glObjectPtrLabelKHR)(const void * ptr, GLsizei length, const GLchar * label) {
+void API_ENTRY(glObjectPtrLabelKHR)(const void *ptr, GLsizei length, const GLchar *label) {
     CALL_GL_API(glObjectPtrLabelKHR, ptr, length, label);
 }
-void API_ENTRY(glGetObjectPtrLabelKHR)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label) {
+void API_ENTRY(glGetObjectPtrLabelKHR)(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label) {
     CALL_GL_API(glGetObjectPtrLabelKHR, ptr, bufSize, length, label);
 }
-void API_ENTRY(glGetPointervKHR)(GLenum pname, void ** params) {
+void API_ENTRY(glGetPointervKHR)(GLenum pname, void **params) {
     CALL_GL_API(glGetPointervKHR, pname, params);
 }
+GLenum API_ENTRY(glGetGraphicsResetStatusKHR)(void) {
+    CALL_GL_API_RETURN(glGetGraphicsResetStatusKHR);
+}
+void API_ENTRY(glReadnPixelsKHR)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
+    CALL_GL_API(glReadnPixelsKHR, x, y, width, height, format, type, bufSize, data);
+}
+void API_ENTRY(glGetnUniformfvKHR)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
+    CALL_GL_API(glGetnUniformfvKHR, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformivKHR)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
+    CALL_GL_API(glGetnUniformivKHR, program, location, bufSize, params);
+}
+void API_ENTRY(glGetnUniformuivKHR)(GLuint program, GLint location, GLsizei bufSize, GLuint *params) {
+    CALL_GL_API(glGetnUniformuivKHR, program, location, bufSize, params);
+}
 void API_ENTRY(glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) {
     CALL_GL_API(glEGLImageTargetTexture2DOES, target, image);
 }
 void API_ENTRY(glEGLImageTargetRenderbufferStorageOES)(GLenum target, GLeglImageOES image) {
     CALL_GL_API(glEGLImageTargetRenderbufferStorageOES, target, image);
 }
-void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary) {
+void API_ENTRY(glCopyImageSubDataOES)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
+    CALL_GL_API(glCopyImageSubDataOES, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
+}
+void API_ENTRY(glEnableiOES)(GLenum target, GLuint index) {
+    CALL_GL_API(glEnableiOES, target, index);
+}
+void API_ENTRY(glDisableiOES)(GLenum target, GLuint index) {
+    CALL_GL_API(glDisableiOES, target, index);
+}
+void API_ENTRY(glBlendEquationiOES)(GLuint buf, GLenum mode) {
+    CALL_GL_API(glBlendEquationiOES, buf, mode);
+}
+void API_ENTRY(glBlendEquationSeparateiOES)(GLuint buf, GLenum modeRGB, GLenum modeAlpha) {
+    CALL_GL_API(glBlendEquationSeparateiOES, buf, modeRGB, modeAlpha);
+}
+void API_ENTRY(glBlendFunciOES)(GLuint buf, GLenum src, GLenum dst) {
+    CALL_GL_API(glBlendFunciOES, buf, src, dst);
+}
+void API_ENTRY(glBlendFuncSeparateiOES)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
+    CALL_GL_API(glBlendFuncSeparateiOES, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+void API_ENTRY(glColorMaskiOES)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
+    CALL_GL_API(glColorMaskiOES, index, r, g, b, a);
+}
+GLboolean API_ENTRY(glIsEnablediOES)(GLenum target, GLuint index) {
+    CALL_GL_API_RETURN(glIsEnablediOES, target, index);
+}
+void API_ENTRY(glDrawElementsBaseVertexOES)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+    CALL_GL_API(glDrawElementsBaseVertexOES, mode, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawRangeElementsBaseVertexOES)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+    CALL_GL_API(glDrawRangeElementsBaseVertexOES, mode, start, end, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertexOES)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
+    CALL_GL_API(glDrawElementsInstancedBaseVertexOES, mode, count, type, indices, instancecount, basevertex);
+}
+void API_ENTRY(glMultiDrawElementsBaseVertexOES)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex) {
+    CALL_GL_API(glMultiDrawElementsBaseVertexOES, mode, count, type, indices, primcount, basevertex);
+}
+void API_ENTRY(glFramebufferTextureOES)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
+    CALL_GL_API(glFramebufferTextureOES, target, attachment, texture, level);
+}
+void API_ENTRY(glGetProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary) {
     CALL_GL_API(glGetProgramBinaryOES, program, bufSize, length, binaryFormat, binary);
 }
-void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void * binary, GLint length) {
+void API_ENTRY(glProgramBinaryOES)(GLuint program, GLenum binaryFormat, const void *binary, GLint length) {
     CALL_GL_API(glProgramBinaryOES, program, binaryFormat, binary, length);
 }
 void * API_ENTRY(glMapBufferOES)(GLenum target, GLenum access) {
@@ -52,67 +109,106 @@
 GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
     CALL_GL_API_RETURN(glUnmapBufferOES, target);
 }
-void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void ** params) {
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void **params) {
     CALL_GL_API(glGetBufferPointervOES, target, pname, params);
 }
+void API_ENTRY(glPrimitiveBoundingBoxOES)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
+    CALL_GL_API(glPrimitiveBoundingBoxOES, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
+}
 void API_ENTRY(glMinSampleShadingOES)(GLfloat value) {
     CALL_GL_API(glMinSampleShadingOES, value);
 }
-void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glPatchParameteriOES)(GLenum pname, GLint value) {
+    CALL_GL_API(glPatchParameteriOES, pname, value);
+}
+void API_ENTRY(glTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexImage3DOES, target, level, internalformat, width, height, depth, border, format, type, pixels);
 }
-void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
 }
 void API_ENTRY(glCopyTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
     CALL_GL_API(glCopyTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, x, y, width, height);
 }
-void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexImage3DOES)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexImage3DOES, target, level, internalformat, width, height, depth, border, imageSize, data);
 }
-void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexSubImage3DOES)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexSubImage3DOES, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
 }
 void API_ENTRY(glFramebufferTexture3DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
     CALL_GL_API(glFramebufferTexture3DOES, target, attachment, textarget, texture, level, zoffset);
 }
+void API_ENTRY(glTexParameterIivOES)(GLenum target, GLenum pname, const GLint *params) {
+    CALL_GL_API(glTexParameterIivOES, target, pname, params);
+}
+void API_ENTRY(glTexParameterIuivOES)(GLenum target, GLenum pname, const GLuint *params) {
+    CALL_GL_API(glTexParameterIuivOES, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIivOES)(GLenum target, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetTexParameterIivOES, target, pname, params);
+}
+void API_ENTRY(glGetTexParameterIuivOES)(GLenum target, GLenum pname, GLuint *params) {
+    CALL_GL_API(glGetTexParameterIuivOES, target, pname, params);
+}
+void API_ENTRY(glSamplerParameterIivOES)(GLuint sampler, GLenum pname, const GLint *param) {
+    CALL_GL_API(glSamplerParameterIivOES, sampler, pname, param);
+}
+void API_ENTRY(glSamplerParameterIuivOES)(GLuint sampler, GLenum pname, const GLuint *param) {
+    CALL_GL_API(glSamplerParameterIuivOES, sampler, pname, param);
+}
+void API_ENTRY(glGetSamplerParameterIivOES)(GLuint sampler, GLenum pname, GLint *params) {
+    CALL_GL_API(glGetSamplerParameterIivOES, sampler, pname, params);
+}
+void API_ENTRY(glGetSamplerParameterIuivOES)(GLuint sampler, GLenum pname, GLuint *params) {
+    CALL_GL_API(glGetSamplerParameterIuivOES, sampler, pname, params);
+}
+void API_ENTRY(glTexBufferOES)(GLenum target, GLenum internalformat, GLuint buffer) {
+    CALL_GL_API(glTexBufferOES, target, internalformat, buffer);
+}
+void API_ENTRY(glTexBufferRangeOES)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) {
+    CALL_GL_API(glTexBufferRangeOES, target, internalformat, buffer, offset, size);
+}
 void API_ENTRY(glTexStorage3DMultisampleOES)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
     CALL_GL_API(glTexStorage3DMultisampleOES, target, samples, internalformat, width, height, depth, fixedsamplelocations);
 }
+void API_ENTRY(glTextureViewOES)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) {
+    CALL_GL_API(glTextureViewOES, texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
+}
 void API_ENTRY(glBindVertexArrayOES)(GLuint array) {
     CALL_GL_API(glBindVertexArrayOES, array);
 }
-void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint * arrays) {
+void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint *arrays) {
     CALL_GL_API(glDeleteVertexArraysOES, n, arrays);
 }
-void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint * arrays) {
+void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint *arrays) {
     CALL_GL_API(glGenVertexArraysOES, n, arrays);
 }
 GLboolean API_ENTRY(glIsVertexArrayOES)(GLuint array) {
     CALL_GL_API_RETURN(glIsVertexArrayOES, array);
 }
-void API_ENTRY(glGetPerfMonitorGroupsAMD)(GLint * numGroups, GLsizei groupsSize, GLuint * groups) {
+void API_ENTRY(glGetPerfMonitorGroupsAMD)(GLint *numGroups, GLsizei groupsSize, GLuint *groups) {
     CALL_GL_API(glGetPerfMonitorGroupsAMD, numGroups, groupsSize, groups);
 }
-void API_ENTRY(glGetPerfMonitorCountersAMD)(GLuint group, GLint * numCounters, GLint * maxActiveCounters, GLsizei counterSize, GLuint * counters) {
+void API_ENTRY(glGetPerfMonitorCountersAMD)(GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters) {
     CALL_GL_API(glGetPerfMonitorCountersAMD, group, numCounters, maxActiveCounters, counterSize, counters);
 }
-void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei * length, GLchar * groupString) {
+void API_ENTRY(glGetPerfMonitorGroupStringAMD)(GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString) {
     CALL_GL_API(glGetPerfMonitorGroupStringAMD, group, bufSize, length, groupString);
 }
-void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei * length, GLchar * counterString) {
+void API_ENTRY(glGetPerfMonitorCounterStringAMD)(GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString) {
     CALL_GL_API(glGetPerfMonitorCounterStringAMD, group, counter, bufSize, length, counterString);
 }
-void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, void * data) {
+void API_ENTRY(glGetPerfMonitorCounterInfoAMD)(GLuint group, GLuint counter, GLenum pname, void *data) {
     CALL_GL_API(glGetPerfMonitorCounterInfoAMD, group, counter, pname, data);
 }
-void API_ENTRY(glGenPerfMonitorsAMD)(GLsizei n, GLuint * monitors) {
+void API_ENTRY(glGenPerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
     CALL_GL_API(glGenPerfMonitorsAMD, n, monitors);
 }
-void API_ENTRY(glDeletePerfMonitorsAMD)(GLsizei n, GLuint * monitors) {
+void API_ENTRY(glDeletePerfMonitorsAMD)(GLsizei n, GLuint *monitors) {
     CALL_GL_API(glDeletePerfMonitorsAMD, n, monitors);
 }
-void API_ENTRY(glSelectPerfMonitorCountersAMD)(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint * counterList) {
+void API_ENTRY(glSelectPerfMonitorCountersAMD)(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList) {
     CALL_GL_API(glSelectPerfMonitorCountersAMD, monitor, enable, group, numCounters, counterList);
 }
 void API_ENTRY(glBeginPerfMonitorAMD)(GLuint monitor) {
@@ -121,7 +217,7 @@
 void API_ENTRY(glEndPerfMonitorAMD)(GLuint monitor) {
     CALL_GL_API(glEndPerfMonitorAMD, monitor);
 }
-void API_ENTRY(glGetPerfMonitorCounterDataAMD)(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint * data, GLint * bytesWritten) {
+void API_ENTRY(glGetPerfMonitorCounterDataAMD)(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten) {
     CALL_GL_API(glGetPerfMonitorCounterDataAMD, monitor, pname, dataSize, data, bytesWritten);
 }
 void API_ENTRY(glBlitFramebufferANGLE)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
@@ -133,13 +229,13 @@
 void API_ENTRY(glDrawArraysInstancedANGLE)(GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
     CALL_GL_API(glDrawArraysInstancedANGLE, mode, first, count, primcount);
 }
-void API_ENTRY(glDrawElementsInstancedANGLE)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) {
+void API_ENTRY(glDrawElementsInstancedANGLE)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) {
     CALL_GL_API(glDrawElementsInstancedANGLE, mode, count, type, indices, primcount);
 }
 void API_ENTRY(glVertexAttribDivisorANGLE)(GLuint index, GLuint divisor) {
     CALL_GL_API(glVertexAttribDivisorANGLE, index, divisor);
 }
-void API_ENTRY(glGetTranslatedShaderSourceANGLE)(GLuint shader, GLsizei bufsize, GLsizei * length, GLchar * source) {
+void API_ENTRY(glGetTranslatedShaderSourceANGLE)(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source) {
     CALL_GL_API(glGetTranslatedShaderSourceANGLE, shader, bufsize, length, source);
 }
 void API_ENTRY(glCopyTextureLevelsAPPLE)(GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount) {
@@ -166,37 +262,61 @@
 void API_ENTRY(glWaitSyncAPPLE)(GLsync sync, GLbitfield flags, GLuint64 timeout) {
     CALL_GL_API(glWaitSyncAPPLE, sync, flags, timeout);
 }
-void API_ENTRY(glGetInteger64vAPPLE)(GLenum pname, GLint64 * params) {
+void API_ENTRY(glGetInteger64vAPPLE)(GLenum pname, GLint64 *params) {
     CALL_GL_API(glGetInteger64vAPPLE, pname, params);
 }
-void API_ENTRY(glGetSyncivAPPLE)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) {
+void API_ENTRY(glGetSyncivAPPLE)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
     CALL_GL_API(glGetSyncivAPPLE, sync, pname, bufSize, length, values);
 }
+void API_ENTRY(glDrawArraysInstancedBaseInstanceEXT)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance) {
+    CALL_GL_API(glDrawArraysInstancedBaseInstanceEXT, mode, first, count, instancecount, baseinstance);
+}
+void API_ENTRY(glDrawElementsInstancedBaseInstanceEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance) {
+    CALL_GL_API(glDrawElementsInstancedBaseInstanceEXT, mode, count, type, indices, instancecount, baseinstance);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertexBaseInstanceEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance) {
+    CALL_GL_API(glDrawElementsInstancedBaseVertexBaseInstanceEXT, mode, count, type, indices, instancecount, basevertex, baseinstance);
+}
+void API_ENTRY(glBindFragDataLocationIndexedEXT)(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name) {
+    CALL_GL_API(glBindFragDataLocationIndexedEXT, program, colorNumber, index, name);
+}
+void API_ENTRY(glBindFragDataLocationEXT)(GLuint program, GLuint color, const GLchar *name) {
+    CALL_GL_API(glBindFragDataLocationEXT, program, color, name);
+}
+GLint API_ENTRY(glGetProgramResourceLocationIndexEXT)(GLuint program, GLenum programInterface, const GLchar *name) {
+    CALL_GL_API_RETURN(glGetProgramResourceLocationIndexEXT, program, programInterface, name);
+}
+GLint API_ENTRY(glGetFragDataIndexEXT)(GLuint program, const GLchar *name) {
+    CALL_GL_API_RETURN(glGetFragDataIndexEXT, program, name);
+}
+void API_ENTRY(glBufferStorageEXT)(GLenum target, GLsizeiptr size, const void *data, GLbitfield flags) {
+    CALL_GL_API(glBufferStorageEXT, target, size, data, flags);
+}
 void API_ENTRY(glCopyImageSubDataEXT)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
     CALL_GL_API(glCopyImageSubDataEXT, srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
 }
-void API_ENTRY(glLabelObjectEXT)(GLenum type, GLuint object, GLsizei length, const GLchar * label) {
+void API_ENTRY(glLabelObjectEXT)(GLenum type, GLuint object, GLsizei length, const GLchar *label) {
     CALL_GL_API(glLabelObjectEXT, type, object, length, label);
 }
-void API_ENTRY(glGetObjectLabelEXT)(GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label) {
+void API_ENTRY(glGetObjectLabelEXT)(GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label) {
     CALL_GL_API(glGetObjectLabelEXT, type, object, bufSize, length, label);
 }
-void API_ENTRY(glInsertEventMarkerEXT)(GLsizei length, const GLchar * marker) {
+void API_ENTRY(glInsertEventMarkerEXT)(GLsizei length, const GLchar *marker) {
     CALL_GL_API(glInsertEventMarkerEXT, length, marker);
 }
-void API_ENTRY(glPushGroupMarkerEXT)(GLsizei length, const GLchar * marker) {
+void API_ENTRY(glPushGroupMarkerEXT)(GLsizei length, const GLchar *marker) {
     CALL_GL_API(glPushGroupMarkerEXT, length, marker);
 }
 void API_ENTRY(glPopGroupMarkerEXT)(void) {
     CALL_GL_API(glPopGroupMarkerEXT);
 }
-void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum * attachments) {
+void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
     CALL_GL_API(glDiscardFramebufferEXT, target, numAttachments, attachments);
 }
-void API_ENTRY(glGenQueriesEXT)(GLsizei n, GLuint * ids) {
+void API_ENTRY(glGenQueriesEXT)(GLsizei n, GLuint *ids) {
     CALL_GL_API(glGenQueriesEXT, n, ids);
 }
-void API_ENTRY(glDeleteQueriesEXT)(GLsizei n, const GLuint * ids) {
+void API_ENTRY(glDeleteQueriesEXT)(GLsizei n, const GLuint *ids) {
     CALL_GL_API(glDeleteQueriesEXT, n, ids);
 }
 GLboolean API_ENTRY(glIsQueryEXT)(GLuint id) {
@@ -211,22 +331,22 @@
 void API_ENTRY(glQueryCounterEXT)(GLuint id, GLenum target) {
     CALL_GL_API(glQueryCounterEXT, id, target);
 }
-void API_ENTRY(glGetQueryivEXT)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetQueryivEXT)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetQueryivEXT, target, pname, params);
 }
-void API_ENTRY(glGetQueryObjectivEXT)(GLuint id, GLenum pname, GLint * params) {
+void API_ENTRY(glGetQueryObjectivEXT)(GLuint id, GLenum pname, GLint *params) {
     CALL_GL_API(glGetQueryObjectivEXT, id, pname, params);
 }
-void API_ENTRY(glGetQueryObjectuivEXT)(GLuint id, GLenum pname, GLuint * params) {
+void API_ENTRY(glGetQueryObjectuivEXT)(GLuint id, GLenum pname, GLuint *params) {
     CALL_GL_API(glGetQueryObjectuivEXT, id, pname, params);
 }
-void API_ENTRY(glGetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64 * params) {
+void API_ENTRY(glGetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64 *params) {
     CALL_GL_API(glGetQueryObjecti64vEXT, id, pname, params);
 }
-void API_ENTRY(glGetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64 * params) {
+void API_ENTRY(glGetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64 *params) {
     CALL_GL_API(glGetQueryObjectui64vEXT, id, pname, params);
 }
-void API_ENTRY(glDrawBuffersEXT)(GLsizei n, const GLenum * bufs) {
+void API_ENTRY(glDrawBuffersEXT)(GLsizei n, const GLenum *bufs) {
     CALL_GL_API(glDrawBuffersEXT, n, bufs);
 }
 void API_ENTRY(glEnableiEXT)(GLenum target, GLuint index) {
@@ -253,10 +373,22 @@
 GLboolean API_ENTRY(glIsEnablediEXT)(GLenum target, GLuint index) {
     CALL_GL_API_RETURN(glIsEnablediEXT, target, index);
 }
+void API_ENTRY(glDrawElementsBaseVertexEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+    CALL_GL_API(glDrawElementsBaseVertexEXT, mode, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawRangeElementsBaseVertexEXT)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex) {
+    CALL_GL_API(glDrawRangeElementsBaseVertexEXT, mode, start, end, count, type, indices, basevertex);
+}
+void API_ENTRY(glDrawElementsInstancedBaseVertexEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex) {
+    CALL_GL_API(glDrawElementsInstancedBaseVertexEXT, mode, count, type, indices, instancecount, basevertex);
+}
+void API_ENTRY(glMultiDrawElementsBaseVertexEXT)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex) {
+    CALL_GL_API(glMultiDrawElementsBaseVertexEXT, mode, count, type, indices, primcount, basevertex);
+}
 void API_ENTRY(glDrawArraysInstancedEXT)(GLenum mode, GLint start, GLsizei count, GLsizei primcount) {
     CALL_GL_API(glDrawArraysInstancedEXT, mode, start, count, primcount);
 }
-void API_ENTRY(glDrawElementsInstancedEXT)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) {
+void API_ENTRY(glDrawElementsInstancedEXT)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) {
     CALL_GL_API(glDrawElementsInstancedEXT, mode, count, type, indices, primcount);
 }
 void API_ENTRY(glFramebufferTextureEXT)(GLenum target, GLenum attachment, GLuint texture, GLint level) {
@@ -271,12 +403,18 @@
 void API_ENTRY(glFlushMappedBufferRangeEXT)(GLenum target, GLintptr offset, GLsizeiptr length) {
     CALL_GL_API(glFlushMappedBufferRangeEXT, target, offset, length);
 }
-void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount) {
+void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) {
     CALL_GL_API(glMultiDrawArraysEXT, mode, first, count, primcount);
 }
-void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount) {
+void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount) {
     CALL_GL_API(glMultiDrawElementsEXT, mode, count, type, indices, primcount);
 }
+void API_ENTRY(glMultiDrawArraysIndirectEXT)(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride) {
+    CALL_GL_API(glMultiDrawArraysIndirectEXT, mode, indirect, drawcount, stride);
+}
+void API_ENTRY(glMultiDrawElementsIndirectEXT)(GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride) {
+    CALL_GL_API(glMultiDrawElementsIndirectEXT, mode, type, indirect, drawcount, stride);
+}
 void API_ENTRY(glRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
     CALL_GL_API(glRenderbufferStorageMultisampleEXT, target, samples, internalformat, width, height);
 }
@@ -286,25 +424,28 @@
 void API_ENTRY(glReadBufferIndexedEXT)(GLenum src, GLint index) {
     CALL_GL_API(glReadBufferIndexedEXT, src, index);
 }
-void API_ENTRY(glDrawBuffersIndexedEXT)(GLint n, const GLenum * location, const GLint * indices) {
+void API_ENTRY(glDrawBuffersIndexedEXT)(GLint n, const GLenum *location, const GLint *indices) {
     CALL_GL_API(glDrawBuffersIndexedEXT, n, location, indices);
 }
-void API_ENTRY(glGetIntegeri_vEXT)(GLenum target, GLuint index, GLint * data) {
+void API_ENTRY(glGetIntegeri_vEXT)(GLenum target, GLuint index, GLint *data) {
     CALL_GL_API(glGetIntegeri_vEXT, target, index, data);
 }
 void API_ENTRY(glPrimitiveBoundingBoxEXT)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
     CALL_GL_API(glPrimitiveBoundingBoxEXT, minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
 }
+void API_ENTRY(glRasterSamplesEXT)(GLuint samples, GLboolean fixedsamplelocations) {
+    CALL_GL_API(glRasterSamplesEXT, samples, fixedsamplelocations);
+}
 GLenum API_ENTRY(glGetGraphicsResetStatusEXT)(void) {
     CALL_GL_API_RETURN(glGetGraphicsResetStatusEXT);
 }
-void API_ENTRY(glReadnPixelsEXT)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data) {
+void API_ENTRY(glReadnPixelsEXT)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
     CALL_GL_API(glReadnPixelsEXT, x, y, width, height, format, type, bufSize, data);
 }
-void API_ENTRY(glGetnUniformfvEXT)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params) {
+void API_ENTRY(glGetnUniformfvEXT)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
     CALL_GL_API(glGetnUniformfvEXT, program, location, bufSize, params);
 }
-void API_ENTRY(glGetnUniformivEXT)(GLuint program, GLint location, GLsizei bufSize, GLint * params) {
+void API_ENTRY(glGetnUniformivEXT)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
     CALL_GL_API(glGetnUniformivEXT, program, location, bufSize, params);
 }
 void API_ENTRY(glActiveShaderProgramEXT)(GLuint pipeline, GLuint program) {
@@ -313,19 +454,19 @@
 void API_ENTRY(glBindProgramPipelineEXT)(GLuint pipeline) {
     CALL_GL_API(glBindProgramPipelineEXT, pipeline);
 }
-GLuint API_ENTRY(glCreateShaderProgramvEXT)(GLenum type, GLsizei count, const GLchar ** strings) {
+GLuint API_ENTRY(glCreateShaderProgramvEXT)(GLenum type, GLsizei count, const GLchar **strings) {
     CALL_GL_API_RETURN(glCreateShaderProgramvEXT, type, count, strings);
 }
-void API_ENTRY(glDeleteProgramPipelinesEXT)(GLsizei n, const GLuint * pipelines) {
+void API_ENTRY(glDeleteProgramPipelinesEXT)(GLsizei n, const GLuint *pipelines) {
     CALL_GL_API(glDeleteProgramPipelinesEXT, n, pipelines);
 }
-void API_ENTRY(glGenProgramPipelinesEXT)(GLsizei n, GLuint * pipelines) {
+void API_ENTRY(glGenProgramPipelinesEXT)(GLsizei n, GLuint *pipelines) {
     CALL_GL_API(glGenProgramPipelinesEXT, n, pipelines);
 }
-void API_ENTRY(glGetProgramPipelineInfoLogEXT)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
+void API_ENTRY(glGetProgramPipelineInfoLogEXT)(GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
     CALL_GL_API(glGetProgramPipelineInfoLogEXT, pipeline, bufSize, length, infoLog);
 }
-void API_ENTRY(glGetProgramPipelineivEXT)(GLuint pipeline, GLenum pname, GLint * params) {
+void API_ENTRY(glGetProgramPipelineivEXT)(GLuint pipeline, GLenum pname, GLint *params) {
     CALL_GL_API(glGetProgramPipelineivEXT, pipeline, pname, params);
 }
 GLboolean API_ENTRY(glIsProgramPipelineEXT)(GLuint pipeline) {
@@ -337,58 +478,58 @@
 void API_ENTRY(glProgramUniform1fEXT)(GLuint program, GLint location, GLfloat v0) {
     CALL_GL_API(glProgramUniform1fEXT, program, location, v0);
 }
-void API_ENTRY(glProgramUniform1fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform1fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform1fvEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform1iEXT)(GLuint program, GLint location, GLint v0) {
     CALL_GL_API(glProgramUniform1iEXT, program, location, v0);
 }
-void API_ENTRY(glProgramUniform1ivEXT)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform1ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform1ivEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform2fEXT)(GLuint program, GLint location, GLfloat v0, GLfloat v1) {
     CALL_GL_API(glProgramUniform2fEXT, program, location, v0, v1);
 }
-void API_ENTRY(glProgramUniform2fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform2fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform2fvEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform2iEXT)(GLuint program, GLint location, GLint v0, GLint v1) {
     CALL_GL_API(glProgramUniform2iEXT, program, location, v0, v1);
 }
-void API_ENTRY(glProgramUniform2ivEXT)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform2ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform2ivEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform3fEXT)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
     CALL_GL_API(glProgramUniform3fEXT, program, location, v0, v1, v2);
 }
-void API_ENTRY(glProgramUniform3fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform3fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform3fvEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform3iEXT)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) {
     CALL_GL_API(glProgramUniform3iEXT, program, location, v0, v1, v2);
 }
-void API_ENTRY(glProgramUniform3ivEXT)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform3ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform3ivEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform4fEXT)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
     CALL_GL_API(glProgramUniform4fEXT, program, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glProgramUniform4fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
+void API_ENTRY(glProgramUniform4fvEXT)(GLuint program, GLint location, GLsizei count, const GLfloat *value) {
     CALL_GL_API(glProgramUniform4fvEXT, program, location, count, value);
 }
 void API_ENTRY(glProgramUniform4iEXT)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
     CALL_GL_API(glProgramUniform4iEXT, program, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glProgramUniform4ivEXT)(GLuint program, GLint location, GLsizei count, const GLint * value) {
+void API_ENTRY(glProgramUniform4ivEXT)(GLuint program, GLint location, GLsizei count, const GLint *value) {
     CALL_GL_API(glProgramUniform4ivEXT, program, location, count, value);
 }
-void API_ENTRY(glProgramUniformMatrix2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix2fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix3fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix4fvEXT, program, location, count, transpose, value);
 }
 void API_ENTRY(glUseProgramStagesEXT)(GLuint pipeline, GLbitfield stages, GLuint program) {
@@ -409,61 +550,64 @@
 void API_ENTRY(glProgramUniform4uiEXT)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
     CALL_GL_API(glProgramUniform4uiEXT, program, location, v0, v1, v2, v3);
 }
-void API_ENTRY(glProgramUniform1uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform1uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform1uivEXT, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform2uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform2uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform2uivEXT, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform3uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform3uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform3uivEXT, program, location, count, value);
 }
-void API_ENTRY(glProgramUniform4uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint * value) {
+void API_ENTRY(glProgramUniform4uivEXT)(GLuint program, GLint location, GLsizei count, const GLuint *value) {
     CALL_GL_API(glProgramUniform4uivEXT, program, location, count, value);
 }
-void API_ENTRY(glProgramUniformMatrix2x3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix2x3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix2x3fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix3x2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix3x2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix3x2fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix2x4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix2x4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix2x4fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix4x2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix4x2fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix4x2fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix3x4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix3x4fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix3x4fvEXT, program, location, count, transpose, value);
 }
-void API_ENTRY(glProgramUniformMatrix4x3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glProgramUniformMatrix4x3fvEXT)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glProgramUniformMatrix4x3fvEXT, program, location, count, transpose, value);
 }
+void API_ENTRY(glTexPageCommitmentEXT)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit) {
+    CALL_GL_API(glTexPageCommitmentEXT, target, level, xoffset, yoffset, zoffset, width, height, depth, commit);
+}
 void API_ENTRY(glPatchParameteriEXT)(GLenum pname, GLint value) {
     CALL_GL_API(glPatchParameteriEXT, pname, value);
 }
-void API_ENTRY(glTexParameterIivEXT)(GLenum target, GLenum pname, const GLint * params) {
+void API_ENTRY(glTexParameterIivEXT)(GLenum target, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexParameterIivEXT, target, pname, params);
 }
-void API_ENTRY(glTexParameterIuivEXT)(GLenum target, GLenum pname, const GLuint * params) {
+void API_ENTRY(glTexParameterIuivEXT)(GLenum target, GLenum pname, const GLuint *params) {
     CALL_GL_API(glTexParameterIuivEXT, target, pname, params);
 }
-void API_ENTRY(glGetTexParameterIivEXT)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetTexParameterIivEXT)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexParameterIivEXT, target, pname, params);
 }
-void API_ENTRY(glGetTexParameterIuivEXT)(GLenum target, GLenum pname, GLuint * params) {
+void API_ENTRY(glGetTexParameterIuivEXT)(GLenum target, GLenum pname, GLuint *params) {
     CALL_GL_API(glGetTexParameterIuivEXT, target, pname, params);
 }
-void API_ENTRY(glSamplerParameterIivEXT)(GLuint sampler, GLenum pname, const GLint * param) {
+void API_ENTRY(glSamplerParameterIivEXT)(GLuint sampler, GLenum pname, const GLint *param) {
     CALL_GL_API(glSamplerParameterIivEXT, sampler, pname, param);
 }
-void API_ENTRY(glSamplerParameterIuivEXT)(GLuint sampler, GLenum pname, const GLuint * param) {
+void API_ENTRY(glSamplerParameterIuivEXT)(GLuint sampler, GLenum pname, const GLuint *param) {
     CALL_GL_API(glSamplerParameterIuivEXT, sampler, pname, param);
 }
-void API_ENTRY(glGetSamplerParameterIivEXT)(GLuint sampler, GLenum pname, GLint * params) {
+void API_ENTRY(glGetSamplerParameterIivEXT)(GLuint sampler, GLenum pname, GLint *params) {
     CALL_GL_API(glGetSamplerParameterIivEXT, sampler, pname, params);
 }
-void API_ENTRY(glGetSamplerParameterIuivEXT)(GLuint sampler, GLenum pname, GLuint * params) {
+void API_ENTRY(glGetSamplerParameterIuivEXT)(GLuint sampler, GLenum pname, GLuint *params) {
     CALL_GL_API(glGetSamplerParameterIuivEXT, sampler, pname, params);
 }
 void API_ENTRY(glTexBufferEXT)(GLenum target, GLenum internalformat, GLuint buffer) {
@@ -499,10 +643,13 @@
 void API_ENTRY(glFramebufferTexture2DMultisampleIMG)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
     CALL_GL_API(glFramebufferTexture2DMultisampleIMG, target, attachment, textarget, texture, level, samples);
 }
+void API_ENTRY(glApplyFramebufferAttachmentCMAAINTEL)(void) {
+    CALL_GL_API(glApplyFramebufferAttachmentCMAAINTEL);
+}
 void API_ENTRY(glBeginPerfQueryINTEL)(GLuint queryHandle) {
     CALL_GL_API(glBeginPerfQueryINTEL, queryHandle);
 }
-void API_ENTRY(glCreatePerfQueryINTEL)(GLuint queryId, GLuint * queryHandle) {
+void API_ENTRY(glCreatePerfQueryINTEL)(GLuint queryId, GLuint *queryHandle) {
     CALL_GL_API(glCreatePerfQueryINTEL, queryId, queryHandle);
 }
 void API_ENTRY(glDeletePerfQueryINTEL)(GLuint queryHandle) {
@@ -511,30 +658,78 @@
 void API_ENTRY(glEndPerfQueryINTEL)(GLuint queryHandle) {
     CALL_GL_API(glEndPerfQueryINTEL, queryHandle);
 }
-void API_ENTRY(glGetFirstPerfQueryIdINTEL)(GLuint * queryId) {
+void API_ENTRY(glGetFirstPerfQueryIdINTEL)(GLuint *queryId) {
     CALL_GL_API(glGetFirstPerfQueryIdINTEL, queryId);
 }
-void API_ENTRY(glGetNextPerfQueryIdINTEL)(GLuint queryId, GLuint * nextQueryId) {
+void API_ENTRY(glGetNextPerfQueryIdINTEL)(GLuint queryId, GLuint *nextQueryId) {
     CALL_GL_API(glGetNextPerfQueryIdINTEL, queryId, nextQueryId);
 }
-void API_ENTRY(glGetPerfCounterInfoINTEL)(GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar * counterName, GLuint counterDescLength, GLchar * counterDesc, GLuint * counterOffset, GLuint * counterDataSize, GLuint * counterTypeEnum, GLuint * counterDataTypeEnum, GLuint64 * rawCounterMaxValue) {
+void API_ENTRY(glGetPerfCounterInfoINTEL)(GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue) {
     CALL_GL_API(glGetPerfCounterInfoINTEL, queryId, counterId, counterNameLength, counterName, counterDescLength, counterDesc, counterOffset, counterDataSize, counterTypeEnum, counterDataTypeEnum, rawCounterMaxValue);
 }
-void API_ENTRY(glGetPerfQueryDataINTEL)(GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid * data, GLuint * bytesWritten) {
+void API_ENTRY(glGetPerfQueryDataINTEL)(GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten) {
     CALL_GL_API(glGetPerfQueryDataINTEL, queryHandle, flags, dataSize, data, bytesWritten);
 }
-void API_ENTRY(glGetPerfQueryIdByNameINTEL)(GLchar * queryName, GLuint * queryId) {
+void API_ENTRY(glGetPerfQueryIdByNameINTEL)(GLchar *queryName, GLuint *queryId) {
     CALL_GL_API(glGetPerfQueryIdByNameINTEL, queryName, queryId);
 }
-void API_ENTRY(glGetPerfQueryInfoINTEL)(GLuint queryId, GLuint queryNameLength, GLchar * queryName, GLuint * dataSize, GLuint * noCounters, GLuint * noInstances, GLuint * capsMask) {
+void API_ENTRY(glGetPerfQueryInfoINTEL)(GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask) {
     CALL_GL_API(glGetPerfQueryInfoINTEL, queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, capsMask);
 }
+GLuint64 API_ENTRY(glGetTextureHandleNV)(GLuint texture) {
+    CALL_GL_API_RETURN(glGetTextureHandleNV, texture);
+}
+GLuint64 API_ENTRY(glGetTextureSamplerHandleNV)(GLuint texture, GLuint sampler) {
+    CALL_GL_API_RETURN(glGetTextureSamplerHandleNV, texture, sampler);
+}
+void API_ENTRY(glMakeTextureHandleResidentNV)(GLuint64 handle) {
+    CALL_GL_API(glMakeTextureHandleResidentNV, handle);
+}
+void API_ENTRY(glMakeTextureHandleNonResidentNV)(GLuint64 handle) {
+    CALL_GL_API(glMakeTextureHandleNonResidentNV, handle);
+}
+GLuint64 API_ENTRY(glGetImageHandleNV)(GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format) {
+    CALL_GL_API_RETURN(glGetImageHandleNV, texture, level, layered, layer, format);
+}
+void API_ENTRY(glMakeImageHandleResidentNV)(GLuint64 handle, GLenum access) {
+    CALL_GL_API(glMakeImageHandleResidentNV, handle, access);
+}
+void API_ENTRY(glMakeImageHandleNonResidentNV)(GLuint64 handle) {
+    CALL_GL_API(glMakeImageHandleNonResidentNV, handle);
+}
+void API_ENTRY(glUniformHandleui64NV)(GLint location, GLuint64 value) {
+    CALL_GL_API(glUniformHandleui64NV, location, value);
+}
+void API_ENTRY(glUniformHandleui64vNV)(GLint location, GLsizei count, const GLuint64 *value) {
+    CALL_GL_API(glUniformHandleui64vNV, location, count, value);
+}
+void API_ENTRY(glProgramUniformHandleui64NV)(GLuint program, GLint location, GLuint64 value) {
+    CALL_GL_API(glProgramUniformHandleui64NV, program, location, value);
+}
+void API_ENTRY(glProgramUniformHandleui64vNV)(GLuint program, GLint location, GLsizei count, const GLuint64 *values) {
+    CALL_GL_API(glProgramUniformHandleui64vNV, program, location, count, values);
+}
+GLboolean API_ENTRY(glIsTextureHandleResidentNV)(GLuint64 handle) {
+    CALL_GL_API_RETURN(glIsTextureHandleResidentNV, handle);
+}
+GLboolean API_ENTRY(glIsImageHandleResidentNV)(GLuint64 handle) {
+    CALL_GL_API_RETURN(glIsImageHandleResidentNV, handle);
+}
 void API_ENTRY(glBlendParameteriNV)(GLenum pname, GLint value) {
     CALL_GL_API(glBlendParameteriNV, pname, value);
 }
 void API_ENTRY(glBlendBarrierNV)(void) {
     CALL_GL_API(glBlendBarrierNV);
 }
+void API_ENTRY(glBeginConditionalRenderNV)(GLuint id, GLenum mode) {
+    CALL_GL_API(glBeginConditionalRenderNV, id, mode);
+}
+void API_ENTRY(glEndConditionalRenderNV)(void) {
+    CALL_GL_API(glEndConditionalRenderNV);
+}
+void API_ENTRY(glSubpixelPrecisionBiasNV)(GLuint xbits, GLuint ybits) {
+    CALL_GL_API(glSubpixelPrecisionBiasNV, xbits, ybits);
+}
 void API_ENTRY(glCopyBufferSubDataNV)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
     CALL_GL_API(glCopyBufferSubDataNV, readTarget, writeTarget, readOffset, writeOffset, size);
 }
@@ -544,19 +739,19 @@
 void API_ENTRY(glCoverageOperationNV)(GLenum operation) {
     CALL_GL_API(glCoverageOperationNV, operation);
 }
-void API_ENTRY(glDrawBuffersNV)(GLsizei n, const GLenum * bufs) {
+void API_ENTRY(glDrawBuffersNV)(GLsizei n, const GLenum *bufs) {
     CALL_GL_API(glDrawBuffersNV, n, bufs);
 }
 void API_ENTRY(glDrawArraysInstancedNV)(GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
     CALL_GL_API(glDrawArraysInstancedNV, mode, first, count, primcount);
 }
-void API_ENTRY(glDrawElementsInstancedNV)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) {
+void API_ENTRY(glDrawElementsInstancedNV)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount) {
     CALL_GL_API(glDrawElementsInstancedNV, mode, count, type, indices, primcount);
 }
-void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint * fences) {
+void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) {
     CALL_GL_API(glDeleteFencesNV, n, fences);
 }
-void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint * fences) {
+void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint *fences) {
     CALL_GL_API(glGenFencesNV, n, fences);
 }
 GLboolean API_ENTRY(glIsFenceNV)(GLuint fence) {
@@ -565,7 +760,7 @@
 GLboolean API_ENTRY(glTestFenceNV)(GLuint fence) {
     CALL_GL_API_RETURN(glTestFenceNV, fence);
 }
-void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint * params) {
+void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint *params) {
     CALL_GL_API(glGetFenceivNV, fence, pname, params);
 }
 void API_ENTRY(glFinishFenceNV)(GLuint fence) {
@@ -574,43 +769,283 @@
 void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) {
     CALL_GL_API(glSetFenceNV, fence, condition);
 }
+void API_ENTRY(glFragmentCoverageColorNV)(GLuint color) {
+    CALL_GL_API(glFragmentCoverageColorNV, color);
+}
 void API_ENTRY(glBlitFramebufferNV)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
     CALL_GL_API(glBlitFramebufferNV, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
 }
+void API_ENTRY(glCoverageModulationTableNV)(GLsizei n, const GLfloat *v) {
+    CALL_GL_API(glCoverageModulationTableNV, n, v);
+}
+void API_ENTRY(glGetCoverageModulationTableNV)(GLsizei bufsize, GLfloat *v) {
+    CALL_GL_API(glGetCoverageModulationTableNV, bufsize, v);
+}
+void API_ENTRY(glCoverageModulationNV)(GLenum components) {
+    CALL_GL_API(glCoverageModulationNV, components);
+}
 void API_ENTRY(glRenderbufferStorageMultisampleNV)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
     CALL_GL_API(glRenderbufferStorageMultisampleNV, target, samples, internalformat, width, height);
 }
 void API_ENTRY(glVertexAttribDivisorNV)(GLuint index, GLuint divisor) {
     CALL_GL_API(glVertexAttribDivisorNV, index, divisor);
 }
-void API_ENTRY(glUniformMatrix2x3fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glGetInternalformatSampleivNV)(GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params) {
+    CALL_GL_API(glGetInternalformatSampleivNV, target, internalformat, samples, pname, bufSize, params);
+}
+void API_ENTRY(glUniformMatrix2x3fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix2x3fvNV, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix3x2fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix3x2fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix3x2fvNV, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix2x4fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix2x4fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix2x4fvNV, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix4x2fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix4x2fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix4x2fvNV, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix3x4fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix3x4fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix3x4fvNV, location, count, transpose, value);
 }
-void API_ENTRY(glUniformMatrix4x3fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
+void API_ENTRY(glUniformMatrix4x3fvNV)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
     CALL_GL_API(glUniformMatrix4x3fvNV, location, count, transpose, value);
 }
+GLuint API_ENTRY(glGenPathsNV)(GLsizei range) {
+    CALL_GL_API_RETURN(glGenPathsNV, range);
+}
+void API_ENTRY(glDeletePathsNV)(GLuint path, GLsizei range) {
+    CALL_GL_API(glDeletePathsNV, path, range);
+}
+GLboolean API_ENTRY(glIsPathNV)(GLuint path) {
+    CALL_GL_API_RETURN(glIsPathNV, path);
+}
+void API_ENTRY(glPathCommandsNV)(GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords) {
+    CALL_GL_API(glPathCommandsNV, path, numCommands, commands, numCoords, coordType, coords);
+}
+void API_ENTRY(glPathCoordsNV)(GLuint path, GLsizei numCoords, GLenum coordType, const void *coords) {
+    CALL_GL_API(glPathCoordsNV, path, numCoords, coordType, coords);
+}
+void API_ENTRY(glPathSubCommandsNV)(GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords) {
+    CALL_GL_API(glPathSubCommandsNV, path, commandStart, commandsToDelete, numCommands, commands, numCoords, coordType, coords);
+}
+void API_ENTRY(glPathSubCoordsNV)(GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords) {
+    CALL_GL_API(glPathSubCoordsNV, path, coordStart, numCoords, coordType, coords);
+}
+void API_ENTRY(glPathStringNV)(GLuint path, GLenum format, GLsizei length, const void *pathString) {
+    CALL_GL_API(glPathStringNV, path, format, length, pathString);
+}
+void API_ENTRY(glPathGlyphsNV)(GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale) {
+    CALL_GL_API(glPathGlyphsNV, firstPathName, fontTarget, fontName, fontStyle, numGlyphs, type, charcodes, handleMissingGlyphs, pathParameterTemplate, emScale);
+}
+void API_ENTRY(glPathGlyphRangeNV)(GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale) {
+    CALL_GL_API(glPathGlyphRangeNV, firstPathName, fontTarget, fontName, fontStyle, firstGlyph, numGlyphs, handleMissingGlyphs, pathParameterTemplate, emScale);
+}
+void API_ENTRY(glWeightPathsNV)(GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights) {
+    CALL_GL_API(glWeightPathsNV, resultPath, numPaths, paths, weights);
+}
+void API_ENTRY(glCopyPathNV)(GLuint resultPath, GLuint srcPath) {
+    CALL_GL_API(glCopyPathNV, resultPath, srcPath);
+}
+void API_ENTRY(glInterpolatePathsNV)(GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight) {
+    CALL_GL_API(glInterpolatePathsNV, resultPath, pathA, pathB, weight);
+}
+void API_ENTRY(glTransformPathNV)(GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glTransformPathNV, resultPath, srcPath, transformType, transformValues);
+}
+void API_ENTRY(glPathParameterivNV)(GLuint path, GLenum pname, const GLint *value) {
+    CALL_GL_API(glPathParameterivNV, path, pname, value);
+}
+void API_ENTRY(glPathParameteriNV)(GLuint path, GLenum pname, GLint value) {
+    CALL_GL_API(glPathParameteriNV, path, pname, value);
+}
+void API_ENTRY(glPathParameterfvNV)(GLuint path, GLenum pname, const GLfloat *value) {
+    CALL_GL_API(glPathParameterfvNV, path, pname, value);
+}
+void API_ENTRY(glPathParameterfNV)(GLuint path, GLenum pname, GLfloat value) {
+    CALL_GL_API(glPathParameterfNV, path, pname, value);
+}
+void API_ENTRY(glPathDashArrayNV)(GLuint path, GLsizei dashCount, const GLfloat *dashArray) {
+    CALL_GL_API(glPathDashArrayNV, path, dashCount, dashArray);
+}
+void API_ENTRY(glPathStencilFuncNV)(GLenum func, GLint ref, GLuint mask) {
+    CALL_GL_API(glPathStencilFuncNV, func, ref, mask);
+}
+void API_ENTRY(glPathStencilDepthOffsetNV)(GLfloat factor, GLfloat units) {
+    CALL_GL_API(glPathStencilDepthOffsetNV, factor, units);
+}
+void API_ENTRY(glStencilFillPathNV)(GLuint path, GLenum fillMode, GLuint mask) {
+    CALL_GL_API(glStencilFillPathNV, path, fillMode, mask);
+}
+void API_ENTRY(glStencilStrokePathNV)(GLuint path, GLint reference, GLuint mask) {
+    CALL_GL_API(glStencilStrokePathNV, path, reference, mask);
+}
+void API_ENTRY(glStencilFillPathInstancedNV)(GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glStencilFillPathInstancedNV, numPaths, pathNameType, paths, pathBase, fillMode, mask, transformType, transformValues);
+}
+void API_ENTRY(glStencilStrokePathInstancedNV)(GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glStencilStrokePathInstancedNV, numPaths, pathNameType, paths, pathBase, reference, mask, transformType, transformValues);
+}
+void API_ENTRY(glPathCoverDepthFuncNV)(GLenum func) {
+    CALL_GL_API(glPathCoverDepthFuncNV, func);
+}
+void API_ENTRY(glCoverFillPathNV)(GLuint path, GLenum coverMode) {
+    CALL_GL_API(glCoverFillPathNV, path, coverMode);
+}
+void API_ENTRY(glCoverStrokePathNV)(GLuint path, GLenum coverMode) {
+    CALL_GL_API(glCoverStrokePathNV, path, coverMode);
+}
+void API_ENTRY(glCoverFillPathInstancedNV)(GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glCoverFillPathInstancedNV, numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+}
+void API_ENTRY(glCoverStrokePathInstancedNV)(GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glCoverStrokePathInstancedNV, numPaths, pathNameType, paths, pathBase, coverMode, transformType, transformValues);
+}
+void API_ENTRY(glGetPathParameterivNV)(GLuint path, GLenum pname, GLint *value) {
+    CALL_GL_API(glGetPathParameterivNV, path, pname, value);
+}
+void API_ENTRY(glGetPathParameterfvNV)(GLuint path, GLenum pname, GLfloat *value) {
+    CALL_GL_API(glGetPathParameterfvNV, path, pname, value);
+}
+void API_ENTRY(glGetPathCommandsNV)(GLuint path, GLubyte *commands) {
+    CALL_GL_API(glGetPathCommandsNV, path, commands);
+}
+void API_ENTRY(glGetPathCoordsNV)(GLuint path, GLfloat *coords) {
+    CALL_GL_API(glGetPathCoordsNV, path, coords);
+}
+void API_ENTRY(glGetPathDashArrayNV)(GLuint path, GLfloat *dashArray) {
+    CALL_GL_API(glGetPathDashArrayNV, path, dashArray);
+}
+void API_ENTRY(glGetPathMetricsNV)(GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics) {
+    CALL_GL_API(glGetPathMetricsNV, metricQueryMask, numPaths, pathNameType, paths, pathBase, stride, metrics);
+}
+void API_ENTRY(glGetPathMetricRangeNV)(GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics) {
+    CALL_GL_API(glGetPathMetricRangeNV, metricQueryMask, firstPathName, numPaths, stride, metrics);
+}
+void API_ENTRY(glGetPathSpacingNV)(GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing) {
+    CALL_GL_API(glGetPathSpacingNV, pathListMode, numPaths, pathNameType, paths, pathBase, advanceScale, kerningScale, transformType, returnedSpacing);
+}
+GLboolean API_ENTRY(glIsPointInFillPathNV)(GLuint path, GLuint mask, GLfloat x, GLfloat y) {
+    CALL_GL_API_RETURN(glIsPointInFillPathNV, path, mask, x, y);
+}
+GLboolean API_ENTRY(glIsPointInStrokePathNV)(GLuint path, GLfloat x, GLfloat y) {
+    CALL_GL_API_RETURN(glIsPointInStrokePathNV, path, x, y);
+}
+GLfloat API_ENTRY(glGetPathLengthNV)(GLuint path, GLsizei startSegment, GLsizei numSegments) {
+    CALL_GL_API_RETURN(glGetPathLengthNV, path, startSegment, numSegments);
+}
+GLboolean API_ENTRY(glPointAlongPathNV)(GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY) {
+    CALL_GL_API_RETURN(glPointAlongPathNV, path, startSegment, numSegments, distance, x, y, tangentX, tangentY);
+}
+void API_ENTRY(glMatrixLoad3x2fNV)(GLenum matrixMode, const GLfloat *m) {
+    CALL_GL_API(glMatrixLoad3x2fNV, matrixMode, m);
+}
+void API_ENTRY(glMatrixLoad3x3fNV)(GLenum matrixMode, const GLfloat *m) {
+    CALL_GL_API(glMatrixLoad3x3fNV, matrixMode, m);
+}
+void API_ENTRY(glMatrixLoadTranspose3x3fNV)(GLenum matrixMode, const GLfloat *m) {
+    CALL_GL_API(glMatrixLoadTranspose3x3fNV, matrixMode, m);
+}
+void API_ENTRY(glMatrixMult3x2fNV)(GLenum matrixMode, const GLfloat *m) {
+    CALL_GL_API(glMatrixMult3x2fNV, matrixMode, m);
+}
+void API_ENTRY(glMatrixMult3x3fNV)(GLenum matrixMode, const GLfloat *m) {
+    CALL_GL_API(glMatrixMult3x3fNV, matrixMode, m);
+}
+void API_ENTRY(glMatrixMultTranspose3x3fNV)(GLenum matrixMode, const GLfloat *m) {
+    CALL_GL_API(glMatrixMultTranspose3x3fNV, matrixMode, m);
+}
+void API_ENTRY(glStencilThenCoverFillPathNV)(GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode) {
+    CALL_GL_API(glStencilThenCoverFillPathNV, path, fillMode, mask, coverMode);
+}
+void API_ENTRY(glStencilThenCoverStrokePathNV)(GLuint path, GLint reference, GLuint mask, GLenum coverMode) {
+    CALL_GL_API(glStencilThenCoverStrokePathNV, path, reference, mask, coverMode);
+}
+void API_ENTRY(glStencilThenCoverFillPathInstancedNV)(GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glStencilThenCoverFillPathInstancedNV, numPaths, pathNameType, paths, pathBase, fillMode, mask, coverMode, transformType, transformValues);
+}
+void API_ENTRY(glStencilThenCoverStrokePathInstancedNV)(GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues) {
+    CALL_GL_API(glStencilThenCoverStrokePathInstancedNV, numPaths, pathNameType, paths, pathBase, reference, mask, coverMode, transformType, transformValues);
+}
+GLenum API_ENTRY(glPathGlyphIndexRangeNV)(GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]) {
+    CALL_GL_API_RETURN(glPathGlyphIndexRangeNV, fontTarget, fontName, fontStyle, pathParameterTemplate, emScale, baseAndCount);
+}
+GLenum API_ENTRY(glPathGlyphIndexArrayNV)(GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale) {
+    CALL_GL_API_RETURN(glPathGlyphIndexArrayNV, firstPathName, fontTarget, fontName, fontStyle, firstGlyphIndex, numGlyphs, pathParameterTemplate, emScale);
+}
+GLenum API_ENTRY(glPathMemoryGlyphIndexArrayNV)(GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale) {
+    CALL_GL_API_RETURN(glPathMemoryGlyphIndexArrayNV, firstPathName, fontTarget, fontSize, fontData, faceIndex, firstGlyphIndex, numGlyphs, pathParameterTemplate, emScale);
+}
+void API_ENTRY(glProgramPathFragmentInputGenNV)(GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs) {
+    CALL_GL_API(glProgramPathFragmentInputGenNV, program, location, genMode, components, coeffs);
+}
+void API_ENTRY(glGetProgramResourcefvNV)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params) {
+    CALL_GL_API(glGetProgramResourcefvNV, program, programInterface, index, propCount, props, bufSize, length, params);
+}
+void API_ENTRY(glPolygonModeNV)(GLenum face, GLenum mode) {
+    CALL_GL_API(glPolygonModeNV, face, mode);
+}
 void API_ENTRY(glReadBufferNV)(GLenum mode) {
     CALL_GL_API(glReadBufferNV, mode);
 }
+void API_ENTRY(glFramebufferSampleLocationsfvNV)(GLenum target, GLuint start, GLsizei count, const GLfloat *v) {
+    CALL_GL_API(glFramebufferSampleLocationsfvNV, target, start, count, v);
+}
+void API_ENTRY(glNamedFramebufferSampleLocationsfvNV)(GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v) {
+    CALL_GL_API(glNamedFramebufferSampleLocationsfvNV, framebuffer, start, count, v);
+}
+void API_ENTRY(glResolveDepthValuesNV)(void) {
+    CALL_GL_API(glResolveDepthValuesNV);
+}
+void API_ENTRY(glViewportArrayvNV)(GLuint first, GLsizei count, const GLfloat *v) {
+    CALL_GL_API(glViewportArrayvNV, first, count, v);
+}
+void API_ENTRY(glViewportIndexedfNV)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h) {
+    CALL_GL_API(glViewportIndexedfNV, index, x, y, w, h);
+}
+void API_ENTRY(glViewportIndexedfvNV)(GLuint index, const GLfloat *v) {
+    CALL_GL_API(glViewportIndexedfvNV, index, v);
+}
+void API_ENTRY(glScissorArrayvNV)(GLuint first, GLsizei count, const GLint *v) {
+    CALL_GL_API(glScissorArrayvNV, first, count, v);
+}
+void API_ENTRY(glScissorIndexedNV)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height) {
+    CALL_GL_API(glScissorIndexedNV, index, left, bottom, width, height);
+}
+void API_ENTRY(glScissorIndexedvNV)(GLuint index, const GLint *v) {
+    CALL_GL_API(glScissorIndexedvNV, index, v);
+}
+void API_ENTRY(glDepthRangeArrayfvNV)(GLuint first, GLsizei count, const GLfloat *v) {
+    CALL_GL_API(glDepthRangeArrayfvNV, first, count, v);
+}
+void API_ENTRY(glDepthRangeIndexedfNV)(GLuint index, GLfloat n, GLfloat f) {
+    CALL_GL_API(glDepthRangeIndexedfNV, index, n, f);
+}
+void API_ENTRY(glGetFloati_vNV)(GLenum target, GLuint index, GLfloat *data) {
+    CALL_GL_API(glGetFloati_vNV, target, index, data);
+}
+void API_ENTRY(glEnableiNV)(GLenum target, GLuint index) {
+    CALL_GL_API(glEnableiNV, target, index);
+}
+void API_ENTRY(glDisableiNV)(GLenum target, GLuint index) {
+    CALL_GL_API(glDisableiNV, target, index);
+}
+GLboolean API_ENTRY(glIsEnablediNV)(GLenum target, GLuint index) {
+    CALL_GL_API_RETURN(glIsEnablediNV, target, index);
+}
+void API_ENTRY(glFramebufferTextureMultiviewOVR)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews) {
+    CALL_GL_API(glFramebufferTextureMultiviewOVR, target, attachment, texture, level, baseViewIndex, numViews);
+}
+void API_ENTRY(glFramebufferTextureMultisampleMultiviewOVR)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews) {
+    CALL_GL_API(glFramebufferTextureMultisampleMultiviewOVR, target, attachment, texture, level, samples, baseViewIndex, numViews);
+}
 void API_ENTRY(glAlphaFuncQCOM)(GLenum func, GLclampf ref) {
     CALL_GL_API(glAlphaFuncQCOM, func, ref);
 }
-void API_ENTRY(glGetDriverControlsQCOM)(GLint * num, GLsizei size, GLuint * driverControls) {
+void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) {
     CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls);
 }
-void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei * length, GLchar * driverControlString) {
+void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString) {
     CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString);
 }
 void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
@@ -619,40 +1054,40 @@
 void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) {
     CALL_GL_API(glDisableDriverControlQCOM, driverControl);
 }
-void API_ENTRY(glExtGetTexturesQCOM)(GLuint * textures, GLint maxTextures, GLint * numTextures) {
+void API_ENTRY(glExtGetTexturesQCOM)(GLuint *textures, GLint maxTextures, GLint *numTextures) {
     CALL_GL_API(glExtGetTexturesQCOM, textures, maxTextures, numTextures);
 }
-void API_ENTRY(glExtGetBuffersQCOM)(GLuint * buffers, GLint maxBuffers, GLint * numBuffers) {
+void API_ENTRY(glExtGetBuffersQCOM)(GLuint *buffers, GLint maxBuffers, GLint *numBuffers) {
     CALL_GL_API(glExtGetBuffersQCOM, buffers, maxBuffers, numBuffers);
 }
-void API_ENTRY(glExtGetRenderbuffersQCOM)(GLuint * renderbuffers, GLint maxRenderbuffers, GLint * numRenderbuffers) {
+void API_ENTRY(glExtGetRenderbuffersQCOM)(GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers) {
     CALL_GL_API(glExtGetRenderbuffersQCOM, renderbuffers, maxRenderbuffers, numRenderbuffers);
 }
-void API_ENTRY(glExtGetFramebuffersQCOM)(GLuint * framebuffers, GLint maxFramebuffers, GLint * numFramebuffers) {
+void API_ENTRY(glExtGetFramebuffersQCOM)(GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers) {
     CALL_GL_API(glExtGetFramebuffersQCOM, framebuffers, maxFramebuffers, numFramebuffers);
 }
-void API_ENTRY(glExtGetTexLevelParameterivQCOM)(GLuint texture, GLenum face, GLint level, GLenum pname, GLint * params) {
+void API_ENTRY(glExtGetTexLevelParameterivQCOM)(GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params) {
     CALL_GL_API(glExtGetTexLevelParameterivQCOM, texture, face, level, pname, params);
 }
 void API_ENTRY(glExtTexObjectStateOverrideiQCOM)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glExtTexObjectStateOverrideiQCOM, target, pname, param);
 }
-void API_ENTRY(glExtGetTexSubImageQCOM)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void * texels) {
+void API_ENTRY(glExtGetTexSubImageQCOM)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels) {
     CALL_GL_API(glExtGetTexSubImageQCOM, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);
 }
-void API_ENTRY(glExtGetBufferPointervQCOM)(GLenum target, void ** params) {
+void API_ENTRY(glExtGetBufferPointervQCOM)(GLenum target, void **params) {
     CALL_GL_API(glExtGetBufferPointervQCOM, target, params);
 }
-void API_ENTRY(glExtGetShadersQCOM)(GLuint * shaders, GLint maxShaders, GLint * numShaders) {
+void API_ENTRY(glExtGetShadersQCOM)(GLuint *shaders, GLint maxShaders, GLint *numShaders) {
     CALL_GL_API(glExtGetShadersQCOM, shaders, maxShaders, numShaders);
 }
-void API_ENTRY(glExtGetProgramsQCOM)(GLuint * programs, GLint maxPrograms, GLint * numPrograms) {
+void API_ENTRY(glExtGetProgramsQCOM)(GLuint *programs, GLint maxPrograms, GLint *numPrograms) {
     CALL_GL_API(glExtGetProgramsQCOM, programs, maxPrograms, numPrograms);
 }
 GLboolean API_ENTRY(glExtIsProgramBinaryQCOM)(GLuint program) {
     CALL_GL_API_RETURN(glExtIsProgramBinaryQCOM, program);
 }
-void API_ENTRY(glExtGetProgramBinarySourceQCOM)(GLuint program, GLenum shadertype, GLchar * source, GLint * length) {
+void API_ENTRY(glExtGetProgramBinarySourceQCOM)(GLuint program, GLenum shadertype, GLchar *source, GLint *length) {
     CALL_GL_API(glExtGetProgramBinarySourceQCOM, program, shadertype, source, length);
 }
 void API_ENTRY(glStartTilingQCOM)(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) {
diff --git a/opengl/libs/GLES_CM/gl_api.in b/opengl/libs/GLES_CM/gl_api.in
index fa975ed..ef383f6 100644
--- a/opengl/libs/GLES_CM/gl_api.in
+++ b/opengl/libs/GLES_CM/gl_api.in
@@ -7,7 +7,7 @@
 void API_ENTRY(glClearDepthf)(GLfloat d) {
     CALL_GL_API(glClearDepthf, d);
 }
-void API_ENTRY(glClipPlanef)(GLenum p, const GLfloat * eqn) {
+void API_ENTRY(glClipPlanef)(GLenum p, const GLfloat *eqn) {
     CALL_GL_API(glClipPlanef, p, eqn);
 }
 void API_ENTRY(glColor4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
@@ -19,55 +19,55 @@
 void API_ENTRY(glFogf)(GLenum pname, GLfloat param) {
     CALL_GL_API(glFogf, pname, param);
 }
-void API_ENTRY(glFogfv)(GLenum pname, const GLfloat * params) {
+void API_ENTRY(glFogfv)(GLenum pname, const GLfloat *params) {
     CALL_GL_API(glFogfv, pname, params);
 }
 void API_ENTRY(glFrustumf)(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
     CALL_GL_API(glFrustumf, l, r, b, t, n, f);
 }
-void API_ENTRY(glGetClipPlanef)(GLenum plane, GLfloat * equation) {
+void API_ENTRY(glGetClipPlanef)(GLenum plane, GLfloat *equation) {
     CALL_GL_API(glGetClipPlanef, plane, equation);
 }
-void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat * data) {
+void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat *data) {
     CALL_GL_API(glGetFloatv, pname, data);
 }
-void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetLightfv)(GLenum light, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetLightfv, light, pname, params);
 }
-void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetMaterialfv)(GLenum face, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetMaterialfv, face, pname, params);
 }
-void API_ENTRY(glGetTexEnvfv)(GLenum target, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetTexEnvfv)(GLenum target, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexEnvfv, target, pname, params);
 }
-void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexParameterfv, target, pname, params);
 }
 void API_ENTRY(glLightModelf)(GLenum pname, GLfloat param) {
     CALL_GL_API(glLightModelf, pname, param);
 }
-void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat * params) {
+void API_ENTRY(glLightModelfv)(GLenum pname, const GLfloat *params) {
     CALL_GL_API(glLightModelfv, pname, params);
 }
 void API_ENTRY(glLightf)(GLenum light, GLenum pname, GLfloat param) {
     CALL_GL_API(glLightf, light, pname, param);
 }
-void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat * params) {
+void API_ENTRY(glLightfv)(GLenum light, GLenum pname, const GLfloat *params) {
     CALL_GL_API(glLightfv, light, pname, params);
 }
 void API_ENTRY(glLineWidth)(GLfloat width) {
     CALL_GL_API(glLineWidth, width);
 }
-void API_ENTRY(glLoadMatrixf)(const GLfloat * m) {
+void API_ENTRY(glLoadMatrixf)(const GLfloat *m) {
     CALL_GL_API(glLoadMatrixf, m);
 }
 void API_ENTRY(glMaterialf)(GLenum face, GLenum pname, GLfloat param) {
     CALL_GL_API(glMaterialf, face, pname, param);
 }
-void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat * params) {
+void API_ENTRY(glMaterialfv)(GLenum face, GLenum pname, const GLfloat *params) {
     CALL_GL_API(glMaterialfv, face, pname, params);
 }
-void API_ENTRY(glMultMatrixf)(const GLfloat * m) {
+void API_ENTRY(glMultMatrixf)(const GLfloat *m) {
     CALL_GL_API(glMultMatrixf, m);
 }
 void API_ENTRY(glMultiTexCoord4f)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
@@ -82,7 +82,7 @@
 void API_ENTRY(glPointParameterf)(GLenum pname, GLfloat param) {
     CALL_GL_API(glPointParameterf, pname, param);
 }
-void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat * params) {
+void API_ENTRY(glPointParameterfv)(GLenum pname, const GLfloat *params) {
     CALL_GL_API(glPointParameterfv, pname, params);
 }
 void API_ENTRY(glPointSize)(GLfloat size) {
@@ -100,13 +100,13 @@
 void API_ENTRY(glTexEnvf)(GLenum target, GLenum pname, GLfloat param) {
     CALL_GL_API(glTexEnvf, target, pname, param);
 }
-void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat * params) {
+void API_ENTRY(glTexEnvfv)(GLenum target, GLenum pname, const GLfloat *params) {
     CALL_GL_API(glTexEnvfv, target, pname, params);
 }
 void API_ENTRY(glTexParameterf)(GLenum target, GLenum pname, GLfloat param) {
     CALL_GL_API(glTexParameterf, target, pname, param);
 }
-void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat * params) {
+void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params) {
     CALL_GL_API(glTexParameterfv, target, pname, params);
 }
 void API_ENTRY(glTranslatef)(GLfloat x, GLfloat y, GLfloat z) {
@@ -127,10 +127,10 @@
 void API_ENTRY(glBlendFunc)(GLenum sfactor, GLenum dfactor) {
     CALL_GL_API(glBlendFunc, sfactor, dfactor);
 }
-void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void * data, GLenum usage) {
+void API_ENTRY(glBufferData)(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
     CALL_GL_API(glBufferData, target, size, data, usage);
 }
-void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data) {
+void API_ENTRY(glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
     CALL_GL_API(glBufferSubData, target, offset, size, data);
 }
 void API_ENTRY(glClear)(GLbitfield mask) {
@@ -148,7 +148,7 @@
 void API_ENTRY(glClientActiveTexture)(GLenum texture) {
     CALL_GL_API(glClientActiveTexture, texture);
 }
-void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed * equation) {
+void API_ENTRY(glClipPlanex)(GLenum plane, const GLfixed *equation) {
     CALL_GL_API(glClipPlanex, plane, equation);
 }
 void API_ENTRY(glColor4ub)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
@@ -160,13 +160,13 @@
 void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
     CALL_GL_API(glColorMask, red, green, blue, alpha);
 }
-void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glColorPointer)(GLint size, GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glColorPointer, size, type, stride, pointer);
 }
-void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
 }
-void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data) {
+void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {
     CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
 }
 void API_ENTRY(glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
@@ -178,10 +178,10 @@
 void API_ENTRY(glCullFace)(GLenum mode) {
     CALL_GL_API(glCullFace, mode);
 }
-void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint * buffers) {
+void API_ENTRY(glDeleteBuffers)(GLsizei n, const GLuint *buffers) {
     CALL_GL_API(glDeleteBuffers, n, buffers);
 }
-void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint * textures) {
+void API_ENTRY(glDeleteTextures)(GLsizei n, const GLuint *textures) {
     CALL_GL_API(glDeleteTextures, n, textures);
 }
 void API_ENTRY(glDepthFunc)(GLenum func) {
@@ -202,7 +202,7 @@
 void API_ENTRY(glDrawArrays)(GLenum mode, GLint first, GLsizei count) {
     CALL_GL_API(glDrawArrays, mode, first, count);
 }
-void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void * indices) {
+void API_ENTRY(glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void *indices) {
     CALL_GL_API(glDrawElements, mode, count, type, indices);
 }
 void API_ENTRY(glEnable)(GLenum cap) {
@@ -220,7 +220,7 @@
 void API_ENTRY(glFogx)(GLenum pname, GLfixed param) {
     CALL_GL_API(glFogx, pname, param);
 }
-void API_ENTRY(glFogxv)(GLenum pname, const GLfixed * param) {
+void API_ENTRY(glFogxv)(GLenum pname, const GLfixed *param) {
     CALL_GL_API(glFogxv, pname, param);
 }
 void API_ENTRY(glFrontFace)(GLenum mode) {
@@ -229,52 +229,52 @@
 void API_ENTRY(glFrustumx)(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
     CALL_GL_API(glFrustumx, l, r, b, t, n, f);
 }
-void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean * data) {
+void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean *data) {
     CALL_GL_API(glGetBooleanv, pname, data);
 }
-void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetBufferParameteriv, target, pname, params);
 }
-void API_ENTRY(glGetClipPlanex)(GLenum plane, GLfixed * equation) {
+void API_ENTRY(glGetClipPlanex)(GLenum plane, GLfixed *equation) {
     CALL_GL_API(glGetClipPlanex, plane, equation);
 }
-void API_ENTRY(glGenBuffers)(GLsizei n, GLuint * buffers) {
+void API_ENTRY(glGenBuffers)(GLsizei n, GLuint *buffers) {
     CALL_GL_API(glGenBuffers, n, buffers);
 }
-void API_ENTRY(glGenTextures)(GLsizei n, GLuint * textures) {
+void API_ENTRY(glGenTextures)(GLsizei n, GLuint *textures) {
     CALL_GL_API(glGenTextures, n, textures);
 }
 GLenum API_ENTRY(glGetError)(void) {
     CALL_GL_API_RETURN(glGetError);
 }
-void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetFixedv)(GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetFixedv, pname, params);
 }
-void API_ENTRY(glGetIntegerv)(GLenum pname, GLint * data) {
+void API_ENTRY(glGetIntegerv)(GLenum pname, GLint *data) {
     CALL_GL_API(glGetIntegerv, pname, data);
 }
-void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetLightxv)(GLenum light, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetLightxv, light, pname, params);
 }
-void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetMaterialxv)(GLenum face, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetMaterialxv, face, pname, params);
 }
-void API_ENTRY(glGetPointerv)(GLenum pname, void ** params) {
+void API_ENTRY(glGetPointerv)(GLenum pname, void **params) {
     CALL_GL_API(glGetPointerv, pname, params);
 }
 const GLubyte * API_ENTRY(__glGetString)(GLenum name) {
     CALL_GL_API_RETURN(glGetString, name);
 }
-void API_ENTRY(glGetTexEnviv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetTexEnviv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexEnviv, target, pname, params);
 }
-void API_ENTRY(glGetTexEnvxv)(GLenum target, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetTexEnvxv)(GLenum target, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexEnvxv, target, pname, params);
 }
-void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexParameteriv, target, pname, params);
 }
-void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetTexParameterxv)(GLenum target, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexParameterxv, target, pname, params);
 }
 void API_ENTRY(glHint)(GLenum target, GLenum mode) {
@@ -292,13 +292,13 @@
 void API_ENTRY(glLightModelx)(GLenum pname, GLfixed param) {
     CALL_GL_API(glLightModelx, pname, param);
 }
-void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed * param) {
+void API_ENTRY(glLightModelxv)(GLenum pname, const GLfixed *param) {
     CALL_GL_API(glLightModelxv, pname, param);
 }
 void API_ENTRY(glLightx)(GLenum light, GLenum pname, GLfixed param) {
     CALL_GL_API(glLightx, light, pname, param);
 }
-void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glLightxv)(GLenum light, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glLightxv, light, pname, params);
 }
 void API_ENTRY(glLineWidthx)(GLfixed width) {
@@ -307,7 +307,7 @@
 void API_ENTRY(glLoadIdentity)(void) {
     CALL_GL_API(glLoadIdentity);
 }
-void API_ENTRY(glLoadMatrixx)(const GLfixed * m) {
+void API_ENTRY(glLoadMatrixx)(const GLfixed *m) {
     CALL_GL_API(glLoadMatrixx, m);
 }
 void API_ENTRY(glLogicOp)(GLenum opcode) {
@@ -316,13 +316,13 @@
 void API_ENTRY(glMaterialx)(GLenum face, GLenum pname, GLfixed param) {
     CALL_GL_API(glMaterialx, face, pname, param);
 }
-void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed * param) {
+void API_ENTRY(glMaterialxv)(GLenum face, GLenum pname, const GLfixed *param) {
     CALL_GL_API(glMaterialxv, face, pname, param);
 }
 void API_ENTRY(glMatrixMode)(GLenum mode) {
     CALL_GL_API(glMatrixMode, mode);
 }
-void API_ENTRY(glMultMatrixx)(const GLfixed * m) {
+void API_ENTRY(glMultMatrixx)(const GLfixed *m) {
     CALL_GL_API(glMultMatrixx, m);
 }
 void API_ENTRY(glMultiTexCoord4x)(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
@@ -331,7 +331,7 @@
 void API_ENTRY(glNormal3x)(GLfixed nx, GLfixed ny, GLfixed nz) {
     CALL_GL_API(glNormal3x, nx, ny, nz);
 }
-void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glNormalPointer)(GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glNormalPointer, type, stride, pointer);
 }
 void API_ENTRY(glOrthox)(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
@@ -343,7 +343,7 @@
 void API_ENTRY(glPointParameterx)(GLenum pname, GLfixed param) {
     CALL_GL_API(glPointParameterx, pname, param);
 }
-void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed * params) {
+void API_ENTRY(glPointParameterxv)(GLenum pname, const GLfixed *params) {
     CALL_GL_API(glPointParameterxv, pname, params);
 }
 void API_ENTRY(glPointSizex)(GLfixed size) {
@@ -358,7 +358,7 @@
 void API_ENTRY(glPushMatrix)(void) {
     CALL_GL_API(glPushMatrix);
 }
-void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels) {
+void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) {
     CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
 }
 void API_ENTRY(glRotatex)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
@@ -388,7 +388,7 @@
 void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) {
     CALL_GL_API(glStencilOp, fail, zfail, zpass);
 }
-void API_ENTRY(glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glTexCoordPointer, size, type, stride, pointer);
 }
 void API_ENTRY(glTexEnvi)(GLenum target, GLenum pname, GLint param) {
@@ -397,13 +397,13 @@
 void API_ENTRY(glTexEnvx)(GLenum target, GLenum pname, GLfixed param) {
     CALL_GL_API(glTexEnvx, target, pname, param);
 }
-void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint * params) {
+void API_ENTRY(glTexEnviv)(GLenum target, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexEnviv, target, pname, params);
 }
-void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glTexEnvxv)(GLenum target, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexEnvxv, target, pname, params);
 }
-void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexImage2D, target, level, internalformat, width, height, border, format, type, pixels);
 }
 void API_ENTRY(glTexParameteri)(GLenum target, GLenum pname, GLint param) {
@@ -412,19 +412,19 @@
 void API_ENTRY(glTexParameterx)(GLenum target, GLenum pname, GLfixed param) {
     CALL_GL_API(glTexParameterx, target, pname, param);
 }
-void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint * params) {
+void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexParameteriv, target, pname, params);
 }
-void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glTexParameterxv)(GLenum target, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexParameterxv, target, pname, params);
 }
-void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) {
+void API_ENTRY(glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
     CALL_GL_API(glTexSubImage2D, target, level, xoffset, yoffset, width, height, format, type, pixels);
 }
 void API_ENTRY(glTranslatex)(GLfixed x, GLfixed y, GLfixed z) {
     CALL_GL_API(glTranslatex, x, y, z);
 }
-void API_ENTRY(glVertexPointer)(GLint size, GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glVertexPointer)(GLint size, GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glVertexPointer, size, type, stride, pointer);
 }
 void API_ENTRY(glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) {
diff --git a/opengl/libs/GLES_CM/glext_api.in b/opengl/libs/GLES_CM/glext_api.in
index c8fba6b..fbf761a 100644
--- a/opengl/libs/GLES_CM/glext_api.in
+++ b/opengl/libs/GLES_CM/glext_api.in
@@ -13,72 +13,6 @@
 void API_ENTRY(glBlendEquationOES)(GLenum mode) {
     CALL_GL_API(glBlendEquationOES, mode);
 }
-void API_ENTRY(glMultiTexCoord1bOES)(GLenum texture, GLbyte s) {
-    CALL_GL_API(glMultiTexCoord1bOES, texture, s);
-}
-void API_ENTRY(glMultiTexCoord1bvOES)(GLenum texture, const GLbyte * coords) {
-    CALL_GL_API(glMultiTexCoord1bvOES, texture, coords);
-}
-void API_ENTRY(glMultiTexCoord2bOES)(GLenum texture, GLbyte s, GLbyte t) {
-    CALL_GL_API(glMultiTexCoord2bOES, texture, s, t);
-}
-void API_ENTRY(glMultiTexCoord2bvOES)(GLenum texture, const GLbyte * coords) {
-    CALL_GL_API(glMultiTexCoord2bvOES, texture, coords);
-}
-void API_ENTRY(glMultiTexCoord3bOES)(GLenum texture, GLbyte s, GLbyte t, GLbyte r) {
-    CALL_GL_API(glMultiTexCoord3bOES, texture, s, t, r);
-}
-void API_ENTRY(glMultiTexCoord3bvOES)(GLenum texture, const GLbyte * coords) {
-    CALL_GL_API(glMultiTexCoord3bvOES, texture, coords);
-}
-void API_ENTRY(glMultiTexCoord4bOES)(GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q) {
-    CALL_GL_API(glMultiTexCoord4bOES, texture, s, t, r, q);
-}
-void API_ENTRY(glMultiTexCoord4bvOES)(GLenum texture, const GLbyte * coords) {
-    CALL_GL_API(glMultiTexCoord4bvOES, texture, coords);
-}
-void API_ENTRY(glTexCoord1bOES)(GLbyte s) {
-    CALL_GL_API(glTexCoord1bOES, s);
-}
-void API_ENTRY(glTexCoord1bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glTexCoord1bvOES, coords);
-}
-void API_ENTRY(glTexCoord2bOES)(GLbyte s, GLbyte t) {
-    CALL_GL_API(glTexCoord2bOES, s, t);
-}
-void API_ENTRY(glTexCoord2bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glTexCoord2bvOES, coords);
-}
-void API_ENTRY(glTexCoord3bOES)(GLbyte s, GLbyte t, GLbyte r) {
-    CALL_GL_API(glTexCoord3bOES, s, t, r);
-}
-void API_ENTRY(glTexCoord3bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glTexCoord3bvOES, coords);
-}
-void API_ENTRY(glTexCoord4bOES)(GLbyte s, GLbyte t, GLbyte r, GLbyte q) {
-    CALL_GL_API(glTexCoord4bOES, s, t, r, q);
-}
-void API_ENTRY(glTexCoord4bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glTexCoord4bvOES, coords);
-}
-void API_ENTRY(glVertex2bOES)(GLbyte x) {
-    CALL_GL_API(glVertex2bOES, x);
-}
-void API_ENTRY(glVertex2bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glVertex2bvOES, coords);
-}
-void API_ENTRY(glVertex3bOES)(GLbyte x, GLbyte y) {
-    CALL_GL_API(glVertex3bOES, x, y);
-}
-void API_ENTRY(glVertex3bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glVertex3bvOES, coords);
-}
-void API_ENTRY(glVertex4bOES)(GLbyte x, GLbyte y, GLbyte z) {
-    CALL_GL_API(glVertex4bOES, x, y, z);
-}
-void API_ENTRY(glVertex4bvOES)(const GLbyte * coords) {
-    CALL_GL_API(glVertex4bvOES, coords);
-}
 void API_ENTRY(glDrawTexsOES)(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) {
     CALL_GL_API(glDrawTexsOES, x, y, z, width, height);
 }
@@ -88,19 +22,19 @@
 void API_ENTRY(glDrawTexxOES)(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) {
     CALL_GL_API(glDrawTexxOES, x, y, z, width, height);
 }
-void API_ENTRY(glDrawTexsvOES)(const GLshort * coords) {
+void API_ENTRY(glDrawTexsvOES)(const GLshort *coords) {
     CALL_GL_API(glDrawTexsvOES, coords);
 }
-void API_ENTRY(glDrawTexivOES)(const GLint * coords) {
+void API_ENTRY(glDrawTexivOES)(const GLint *coords) {
     CALL_GL_API(glDrawTexivOES, coords);
 }
-void API_ENTRY(glDrawTexxvOES)(const GLfixed * coords) {
+void API_ENTRY(glDrawTexxvOES)(const GLfixed *coords) {
     CALL_GL_API(glDrawTexxvOES, coords);
 }
 void API_ENTRY(glDrawTexfOES)(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) {
     CALL_GL_API(glDrawTexfOES, x, y, z, width, height);
 }
-void API_ENTRY(glDrawTexfvOES)(const GLfloat * coords) {
+void API_ENTRY(glDrawTexfvOES)(const GLfloat *coords) {
     CALL_GL_API(glDrawTexfvOES, coords);
 }
 void API_ENTRY(glAlphaFuncxOES)(GLenum func, GLfixed ref) {
@@ -112,7 +46,7 @@
 void API_ENTRY(glClearDepthxOES)(GLfixed depth) {
     CALL_GL_API(glClearDepthxOES, depth);
 }
-void API_ENTRY(glClipPlanexOES)(GLenum plane, const GLfixed * equation) {
+void API_ENTRY(glClipPlanexOES)(GLenum plane, const GLfixed *equation) {
     CALL_GL_API(glClipPlanexOES, plane, equation);
 }
 void API_ENTRY(glColor4xOES)(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
@@ -124,49 +58,49 @@
 void API_ENTRY(glFogxOES)(GLenum pname, GLfixed param) {
     CALL_GL_API(glFogxOES, pname, param);
 }
-void API_ENTRY(glFogxvOES)(GLenum pname, const GLfixed * param) {
+void API_ENTRY(glFogxvOES)(GLenum pname, const GLfixed *param) {
     CALL_GL_API(glFogxvOES, pname, param);
 }
 void API_ENTRY(glFrustumxOES)(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
     CALL_GL_API(glFrustumxOES, l, r, b, t, n, f);
 }
-void API_ENTRY(glGetClipPlanexOES)(GLenum plane, GLfixed * equation) {
+void API_ENTRY(glGetClipPlanexOES)(GLenum plane, GLfixed *equation) {
     CALL_GL_API(glGetClipPlanexOES, plane, equation);
 }
-void API_ENTRY(glGetFixedvOES)(GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetFixedvOES)(GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetFixedvOES, pname, params);
 }
-void API_ENTRY(glGetTexEnvxvOES)(GLenum target, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetTexEnvxvOES)(GLenum target, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexEnvxvOES, target, pname, params);
 }
-void API_ENTRY(glGetTexParameterxvOES)(GLenum target, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetTexParameterxvOES)(GLenum target, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexParameterxvOES, target, pname, params);
 }
 void API_ENTRY(glLightModelxOES)(GLenum pname, GLfixed param) {
     CALL_GL_API(glLightModelxOES, pname, param);
 }
-void API_ENTRY(glLightModelxvOES)(GLenum pname, const GLfixed * param) {
+void API_ENTRY(glLightModelxvOES)(GLenum pname, const GLfixed *param) {
     CALL_GL_API(glLightModelxvOES, pname, param);
 }
 void API_ENTRY(glLightxOES)(GLenum light, GLenum pname, GLfixed param) {
     CALL_GL_API(glLightxOES, light, pname, param);
 }
-void API_ENTRY(glLightxvOES)(GLenum light, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glLightxvOES)(GLenum light, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glLightxvOES, light, pname, params);
 }
 void API_ENTRY(glLineWidthxOES)(GLfixed width) {
     CALL_GL_API(glLineWidthxOES, width);
 }
-void API_ENTRY(glLoadMatrixxOES)(const GLfixed * m) {
+void API_ENTRY(glLoadMatrixxOES)(const GLfixed *m) {
     CALL_GL_API(glLoadMatrixxOES, m);
 }
 void API_ENTRY(glMaterialxOES)(GLenum face, GLenum pname, GLfixed param) {
     CALL_GL_API(glMaterialxOES, face, pname, param);
 }
-void API_ENTRY(glMaterialxvOES)(GLenum face, GLenum pname, const GLfixed * param) {
+void API_ENTRY(glMaterialxvOES)(GLenum face, GLenum pname, const GLfixed *param) {
     CALL_GL_API(glMaterialxvOES, face, pname, param);
 }
-void API_ENTRY(glMultMatrixxOES)(const GLfixed * m) {
+void API_ENTRY(glMultMatrixxOES)(const GLfixed *m) {
     CALL_GL_API(glMultMatrixxOES, m);
 }
 void API_ENTRY(glMultiTexCoord4xOES)(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
@@ -178,7 +112,7 @@
 void API_ENTRY(glOrthoxOES)(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
     CALL_GL_API(glOrthoxOES, l, r, b, t, n, f);
 }
-void API_ENTRY(glPointParameterxvOES)(GLenum pname, const GLfixed * params) {
+void API_ENTRY(glPointParameterxvOES)(GLenum pname, const GLfixed *params) {
     CALL_GL_API(glPointParameterxvOES, pname, params);
 }
 void API_ENTRY(glPointSizexOES)(GLfixed size) {
@@ -190,31 +124,28 @@
 void API_ENTRY(glRotatexOES)(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
     CALL_GL_API(glRotatexOES, angle, x, y, z);
 }
-void API_ENTRY(glSampleCoverageOES)(GLfixed value, GLboolean invert) {
-    CALL_GL_API(glSampleCoverageOES, value, invert);
-}
 void API_ENTRY(glScalexOES)(GLfixed x, GLfixed y, GLfixed z) {
     CALL_GL_API(glScalexOES, x, y, z);
 }
 void API_ENTRY(glTexEnvxOES)(GLenum target, GLenum pname, GLfixed param) {
     CALL_GL_API(glTexEnvxOES, target, pname, param);
 }
-void API_ENTRY(glTexEnvxvOES)(GLenum target, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glTexEnvxvOES)(GLenum target, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexEnvxvOES, target, pname, params);
 }
 void API_ENTRY(glTexParameterxOES)(GLenum target, GLenum pname, GLfixed param) {
     CALL_GL_API(glTexParameterxOES, target, pname, param);
 }
-void API_ENTRY(glTexParameterxvOES)(GLenum target, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glTexParameterxvOES)(GLenum target, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexParameterxvOES, target, pname, params);
 }
 void API_ENTRY(glTranslatexOES)(GLfixed x, GLfixed y, GLfixed z) {
     CALL_GL_API(glTranslatexOES, x, y, z);
 }
-void API_ENTRY(glGetLightxvOES)(GLenum light, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetLightxvOES)(GLenum light, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetLightxvOES, light, pname, params);
 }
-void API_ENTRY(glGetMaterialxvOES)(GLenum face, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetMaterialxvOES)(GLenum face, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetMaterialxvOES, face, pname, params);
 }
 void API_ENTRY(glPointParameterxOES)(GLenum pname, GLfixed param) {
@@ -223,13 +154,13 @@
 void API_ENTRY(glSampleCoveragexOES)(GLclampx value, GLboolean invert) {
     CALL_GL_API(glSampleCoveragexOES, value, invert);
 }
-void API_ENTRY(glGetTexGenxvOES)(GLenum coord, GLenum pname, GLfixed * params) {
+void API_ENTRY(glGetTexGenxvOES)(GLenum coord, GLenum pname, GLfixed *params) {
     CALL_GL_API(glGetTexGenxvOES, coord, pname, params);
 }
 void API_ENTRY(glTexGenxOES)(GLenum coord, GLenum pname, GLfixed param) {
     CALL_GL_API(glTexGenxOES, coord, pname, param);
 }
-void API_ENTRY(glTexGenxvOES)(GLenum coord, GLenum pname, const GLfixed * params) {
+void API_ENTRY(glTexGenxvOES)(GLenum coord, GLenum pname, const GLfixed *params) {
     CALL_GL_API(glTexGenxvOES, coord, pname, params);
 }
 GLboolean API_ENTRY(glIsRenderbufferOES)(GLuint renderbuffer) {
@@ -238,16 +169,16 @@
 void API_ENTRY(glBindRenderbufferOES)(GLenum target, GLuint renderbuffer) {
     CALL_GL_API(glBindRenderbufferOES, target, renderbuffer);
 }
-void API_ENTRY(glDeleteRenderbuffersOES)(GLsizei n, const GLuint * renderbuffers) {
+void API_ENTRY(glDeleteRenderbuffersOES)(GLsizei n, const GLuint *renderbuffers) {
     CALL_GL_API(glDeleteRenderbuffersOES, n, renderbuffers);
 }
-void API_ENTRY(glGenRenderbuffersOES)(GLsizei n, GLuint * renderbuffers) {
+void API_ENTRY(glGenRenderbuffersOES)(GLsizei n, GLuint *renderbuffers) {
     CALL_GL_API(glGenRenderbuffersOES, n, renderbuffers);
 }
 void API_ENTRY(glRenderbufferStorageOES)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
     CALL_GL_API(glRenderbufferStorageOES, target, internalformat, width, height);
 }
-void API_ENTRY(glGetRenderbufferParameterivOES)(GLenum target, GLenum pname, GLint * params) {
+void API_ENTRY(glGetRenderbufferParameterivOES)(GLenum target, GLenum pname, GLint *params) {
     CALL_GL_API(glGetRenderbufferParameterivOES, target, pname, params);
 }
 GLboolean API_ENTRY(glIsFramebufferOES)(GLuint framebuffer) {
@@ -256,10 +187,10 @@
 void API_ENTRY(glBindFramebufferOES)(GLenum target, GLuint framebuffer) {
     CALL_GL_API(glBindFramebufferOES, target, framebuffer);
 }
-void API_ENTRY(glDeleteFramebuffersOES)(GLsizei n, const GLuint * framebuffers) {
+void API_ENTRY(glDeleteFramebuffersOES)(GLsizei n, const GLuint *framebuffers) {
     CALL_GL_API(glDeleteFramebuffersOES, n, framebuffers);
 }
-void API_ENTRY(glGenFramebuffersOES)(GLsizei n, GLuint * framebuffers) {
+void API_ENTRY(glGenFramebuffersOES)(GLsizei n, GLuint *framebuffers) {
     CALL_GL_API(glGenFramebuffersOES, n, framebuffers);
 }
 GLenum API_ENTRY(glCheckFramebufferStatusOES)(GLenum target) {
@@ -271,7 +202,7 @@
 void API_ENTRY(glFramebufferTexture2DOES)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
     CALL_GL_API(glFramebufferTexture2DOES, target, attachment, textarget, texture, level);
 }
-void API_ENTRY(glGetFramebufferAttachmentParameterivOES)(GLenum target, GLenum attachment, GLenum pname, GLint * params) {
+void API_ENTRY(glGetFramebufferAttachmentParameterivOES)(GLenum target, GLenum attachment, GLenum pname, GLint *params) {
     CALL_GL_API(glGetFramebufferAttachmentParameterivOES, target, attachment, pname, params);
 }
 void API_ENTRY(glGenerateMipmapOES)(GLenum target) {
@@ -283,7 +214,7 @@
 GLboolean API_ENTRY(glUnmapBufferOES)(GLenum target) {
     CALL_GL_API_RETURN(glUnmapBufferOES, target);
 }
-void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void ** params) {
+void API_ENTRY(glGetBufferPointervOES)(GLenum target, GLenum pname, void **params) {
     CALL_GL_API(glGetBufferPointervOES, target, pname, params);
 }
 void API_ENTRY(glCurrentPaletteMatrixOES)(GLuint matrixpaletteindex) {
@@ -292,22 +223,22 @@
 void API_ENTRY(glLoadPaletteFromModelViewMatrixOES)(void) {
     CALL_GL_API(glLoadPaletteFromModelViewMatrixOES);
 }
-void API_ENTRY(glMatrixIndexPointerOES)(GLint size, GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glMatrixIndexPointerOES)(GLint size, GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glMatrixIndexPointerOES, size, type, stride, pointer);
 }
-void API_ENTRY(glWeightPointerOES)(GLint size, GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glWeightPointerOES)(GLint size, GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glWeightPointerOES, size, type, stride, pointer);
 }
-void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const void * pointer) {
+void API_ENTRY(glPointSizePointerOES)(GLenum type, GLsizei stride, const void *pointer) {
     CALL_GL_API(glPointSizePointerOES, type, stride, pointer);
 }
-GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed * mantissa, GLint * exponent) {
+GLbitfield API_ENTRY(glQueryMatrixxOES)(GLfixed *mantissa, GLint *exponent) {
     CALL_GL_API_RETURN(glQueryMatrixxOES, mantissa, exponent);
 }
 void API_ENTRY(glClearDepthfOES)(GLclampf depth) {
     CALL_GL_API(glClearDepthfOES, depth);
 }
-void API_ENTRY(glClipPlanefOES)(GLenum plane, const GLfloat * equation) {
+void API_ENTRY(glClipPlanefOES)(GLenum plane, const GLfloat *equation) {
     CALL_GL_API(glClipPlanefOES, plane, equation);
 }
 void API_ENTRY(glDepthRangefOES)(GLclampf n, GLclampf f) {
@@ -316,7 +247,7 @@
 void API_ENTRY(glFrustumfOES)(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
     CALL_GL_API(glFrustumfOES, l, r, b, t, n, f);
 }
-void API_ENTRY(glGetClipPlanefOES)(GLenum plane, GLfloat * equation) {
+void API_ENTRY(glGetClipPlanefOES)(GLenum plane, GLfloat *equation) {
     CALL_GL_API(glGetClipPlanefOES, plane, equation);
 }
 void API_ENTRY(glOrthofOES)(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
@@ -325,28 +256,28 @@
 void API_ENTRY(glTexGenfOES)(GLenum coord, GLenum pname, GLfloat param) {
     CALL_GL_API(glTexGenfOES, coord, pname, param);
 }
-void API_ENTRY(glTexGenfvOES)(GLenum coord, GLenum pname, const GLfloat * params) {
+void API_ENTRY(glTexGenfvOES)(GLenum coord, GLenum pname, const GLfloat *params) {
     CALL_GL_API(glTexGenfvOES, coord, pname, params);
 }
 void API_ENTRY(glTexGeniOES)(GLenum coord, GLenum pname, GLint param) {
     CALL_GL_API(glTexGeniOES, coord, pname, param);
 }
-void API_ENTRY(glTexGenivOES)(GLenum coord, GLenum pname, const GLint * params) {
+void API_ENTRY(glTexGenivOES)(GLenum coord, GLenum pname, const GLint *params) {
     CALL_GL_API(glTexGenivOES, coord, pname, params);
 }
-void API_ENTRY(glGetTexGenfvOES)(GLenum coord, GLenum pname, GLfloat * params) {
+void API_ENTRY(glGetTexGenfvOES)(GLenum coord, GLenum pname, GLfloat *params) {
     CALL_GL_API(glGetTexGenfvOES, coord, pname, params);
 }
-void API_ENTRY(glGetTexGenivOES)(GLenum coord, GLenum pname, GLint * params) {
+void API_ENTRY(glGetTexGenivOES)(GLenum coord, GLenum pname, GLint *params) {
     CALL_GL_API(glGetTexGenivOES, coord, pname, params);
 }
 void API_ENTRY(glBindVertexArrayOES)(GLuint array) {
     CALL_GL_API(glBindVertexArrayOES, array);
 }
-void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint * arrays) {
+void API_ENTRY(glDeleteVertexArraysOES)(GLsizei n, const GLuint *arrays) {
     CALL_GL_API(glDeleteVertexArraysOES, n, arrays);
 }
-void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint * arrays) {
+void API_ENTRY(glGenVertexArraysOES)(GLsizei n, GLuint *arrays) {
     CALL_GL_API(glGenVertexArraysOES, n, arrays);
 }
 GLboolean API_ENTRY(glIsVertexArrayOES)(GLuint array) {
@@ -376,13 +307,13 @@
 void API_ENTRY(glWaitSyncAPPLE)(GLsync sync, GLbitfield flags, GLuint64 timeout) {
     CALL_GL_API(glWaitSyncAPPLE, sync, flags, timeout);
 }
-void API_ENTRY(glGetInteger64vAPPLE)(GLenum pname, GLint64 * params) {
+void API_ENTRY(glGetInteger64vAPPLE)(GLenum pname, GLint64 *params) {
     CALL_GL_API(glGetInteger64vAPPLE, pname, params);
 }
-void API_ENTRY(glGetSyncivAPPLE)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) {
+void API_ENTRY(glGetSyncivAPPLE)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values) {
     CALL_GL_API(glGetSyncivAPPLE, sync, pname, bufSize, length, values);
 }
-void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum * attachments) {
+void API_ENTRY(glDiscardFramebufferEXT)(GLenum target, GLsizei numAttachments, const GLenum *attachments) {
     CALL_GL_API(glDiscardFramebufferEXT, target, numAttachments, attachments);
 }
 void * API_ENTRY(glMapBufferRangeEXT)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
@@ -391,10 +322,10 @@
 void API_ENTRY(glFlushMappedBufferRangeEXT)(GLenum target, GLintptr offset, GLsizeiptr length) {
     CALL_GL_API(glFlushMappedBufferRangeEXT, target, offset, length);
 }
-void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount) {
+void API_ENTRY(glMultiDrawArraysEXT)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount) {
     CALL_GL_API(glMultiDrawArraysEXT, mode, first, count, primcount);
 }
-void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount) {
+void API_ENTRY(glMultiDrawElementsEXT)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount) {
     CALL_GL_API(glMultiDrawElementsEXT, mode, count, type, indices, primcount);
 }
 void API_ENTRY(glRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
@@ -406,13 +337,13 @@
 GLenum API_ENTRY(glGetGraphicsResetStatusEXT)(void) {
     CALL_GL_API_RETURN(glGetGraphicsResetStatusEXT);
 }
-void API_ENTRY(glReadnPixelsEXT)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data) {
+void API_ENTRY(glReadnPixelsEXT)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data) {
     CALL_GL_API(glReadnPixelsEXT, x, y, width, height, format, type, bufSize, data);
 }
-void API_ENTRY(glGetnUniformfvEXT)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params) {
+void API_ENTRY(glGetnUniformfvEXT)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params) {
     CALL_GL_API(glGetnUniformfvEXT, program, location, bufSize, params);
 }
-void API_ENTRY(glGetnUniformivEXT)(GLuint program, GLint location, GLsizei bufSize, GLint * params) {
+void API_ENTRY(glGetnUniformivEXT)(GLuint program, GLint location, GLsizei bufSize, GLint *params) {
     CALL_GL_API(glGetnUniformivEXT, program, location, bufSize, params);
 }
 void API_ENTRY(glTexStorage1DEXT)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) {
@@ -439,16 +370,16 @@
 void API_ENTRY(glFramebufferTexture2DMultisampleIMG)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
     CALL_GL_API(glFramebufferTexture2DMultisampleIMG, target, attachment, textarget, texture, level, samples);
 }
-void API_ENTRY(glClipPlanefIMG)(GLenum p, const GLfloat * eqn) {
+void API_ENTRY(glClipPlanefIMG)(GLenum p, const GLfloat *eqn) {
     CALL_GL_API(glClipPlanefIMG, p, eqn);
 }
-void API_ENTRY(glClipPlanexIMG)(GLenum p, const GLfixed * eqn) {
+void API_ENTRY(glClipPlanexIMG)(GLenum p, const GLfixed *eqn) {
     CALL_GL_API(glClipPlanexIMG, p, eqn);
 }
-void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint * fences) {
+void API_ENTRY(glDeleteFencesNV)(GLsizei n, const GLuint *fences) {
     CALL_GL_API(glDeleteFencesNV, n, fences);
 }
-void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint * fences) {
+void API_ENTRY(glGenFencesNV)(GLsizei n, GLuint *fences) {
     CALL_GL_API(glGenFencesNV, n, fences);
 }
 GLboolean API_ENTRY(glIsFenceNV)(GLuint fence) {
@@ -457,7 +388,7 @@
 GLboolean API_ENTRY(glTestFenceNV)(GLuint fence) {
     CALL_GL_API_RETURN(glTestFenceNV, fence);
 }
-void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint * params) {
+void API_ENTRY(glGetFenceivNV)(GLuint fence, GLenum pname, GLint *params) {
     CALL_GL_API(glGetFenceivNV, fence, pname, params);
 }
 void API_ENTRY(glFinishFenceNV)(GLuint fence) {
@@ -466,10 +397,10 @@
 void API_ENTRY(glSetFenceNV)(GLuint fence, GLenum condition) {
     CALL_GL_API(glSetFenceNV, fence, condition);
 }
-void API_ENTRY(glGetDriverControlsQCOM)(GLint * num, GLsizei size, GLuint * driverControls) {
+void API_ENTRY(glGetDriverControlsQCOM)(GLint *num, GLsizei size, GLuint *driverControls) {
     CALL_GL_API(glGetDriverControlsQCOM, num, size, driverControls);
 }
-void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei * length, GLchar * driverControlString) {
+void API_ENTRY(glGetDriverControlStringQCOM)(GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString) {
     CALL_GL_API(glGetDriverControlStringQCOM, driverControl, bufSize, length, driverControlString);
 }
 void API_ENTRY(glEnableDriverControlQCOM)(GLuint driverControl) {
@@ -478,40 +409,40 @@
 void API_ENTRY(glDisableDriverControlQCOM)(GLuint driverControl) {
     CALL_GL_API(glDisableDriverControlQCOM, driverControl);
 }
-void API_ENTRY(glExtGetTexturesQCOM)(GLuint * textures, GLint maxTextures, GLint * numTextures) {
+void API_ENTRY(glExtGetTexturesQCOM)(GLuint *textures, GLint maxTextures, GLint *numTextures) {
     CALL_GL_API(glExtGetTexturesQCOM, textures, maxTextures, numTextures);
 }
-void API_ENTRY(glExtGetBuffersQCOM)(GLuint * buffers, GLint maxBuffers, GLint * numBuffers) {
+void API_ENTRY(glExtGetBuffersQCOM)(GLuint *buffers, GLint maxBuffers, GLint *numBuffers) {
     CALL_GL_API(glExtGetBuffersQCOM, buffers, maxBuffers, numBuffers);
 }
-void API_ENTRY(glExtGetRenderbuffersQCOM)(GLuint * renderbuffers, GLint maxRenderbuffers, GLint * numRenderbuffers) {
+void API_ENTRY(glExtGetRenderbuffersQCOM)(GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers) {
     CALL_GL_API(glExtGetRenderbuffersQCOM, renderbuffers, maxRenderbuffers, numRenderbuffers);
 }
-void API_ENTRY(glExtGetFramebuffersQCOM)(GLuint * framebuffers, GLint maxFramebuffers, GLint * numFramebuffers) {
+void API_ENTRY(glExtGetFramebuffersQCOM)(GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers) {
     CALL_GL_API(glExtGetFramebuffersQCOM, framebuffers, maxFramebuffers, numFramebuffers);
 }
-void API_ENTRY(glExtGetTexLevelParameterivQCOM)(GLuint texture, GLenum face, GLint level, GLenum pname, GLint * params) {
+void API_ENTRY(glExtGetTexLevelParameterivQCOM)(GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params) {
     CALL_GL_API(glExtGetTexLevelParameterivQCOM, texture, face, level, pname, params);
 }
 void API_ENTRY(glExtTexObjectStateOverrideiQCOM)(GLenum target, GLenum pname, GLint param) {
     CALL_GL_API(glExtTexObjectStateOverrideiQCOM, target, pname, param);
 }
-void API_ENTRY(glExtGetTexSubImageQCOM)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void * texels) {
+void API_ENTRY(glExtGetTexSubImageQCOM)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels) {
     CALL_GL_API(glExtGetTexSubImageQCOM, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);
 }
-void API_ENTRY(glExtGetBufferPointervQCOM)(GLenum target, void ** params) {
+void API_ENTRY(glExtGetBufferPointervQCOM)(GLenum target, void **params) {
     CALL_GL_API(glExtGetBufferPointervQCOM, target, params);
 }
-void API_ENTRY(glExtGetShadersQCOM)(GLuint * shaders, GLint maxShaders, GLint * numShaders) {
+void API_ENTRY(glExtGetShadersQCOM)(GLuint *shaders, GLint maxShaders, GLint *numShaders) {
     CALL_GL_API(glExtGetShadersQCOM, shaders, maxShaders, numShaders);
 }
-void API_ENTRY(glExtGetProgramsQCOM)(GLuint * programs, GLint maxPrograms, GLint * numPrograms) {
+void API_ENTRY(glExtGetProgramsQCOM)(GLuint *programs, GLint maxPrograms, GLint *numPrograms) {
     CALL_GL_API(glExtGetProgramsQCOM, programs, maxPrograms, numPrograms);
 }
 GLboolean API_ENTRY(glExtIsProgramBinaryQCOM)(GLuint program) {
     CALL_GL_API_RETURN(glExtIsProgramBinaryQCOM, program);
 }
-void API_ENTRY(glExtGetProgramBinarySourceQCOM)(GLuint program, GLenum shadertype, GLchar * source, GLint * length) {
+void API_ENTRY(glExtGetProgramBinarySourceQCOM)(GLuint program, GLenum shadertype, GLchar *source, GLint *length) {
     CALL_GL_API(glExtGetProgramBinarySourceQCOM, program, shadertype, source, length);
 }
 void API_ENTRY(glStartTilingQCOM)(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) {
diff --git a/opengl/libs/GLES_trace/.gitignore b/opengl/libs/GLES_trace/.gitignore
deleted file mode 100644
index 8df825e..0000000
--- a/opengl/libs/GLES_trace/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-java
-*.pyc
-*.swp
-pyratemp.py
diff --git a/opengl/libs/GLES_trace/Android.mk b/opengl/libs/GLES_trace/Android.mk
deleted file mode 100644
index 24c4be2..0000000
--- a/opengl/libs/GLES_trace/Android.mk
+++ /dev/null
@@ -1,34 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-LOCAL_SRC_FILES := \
-    src/gltrace_api.cpp \
-    src/gltrace_context.cpp \
-    src/gltrace_egl.cpp \
-    src/gltrace_eglapi.cpp \
-    src/gltrace_fixup.cpp \
-    src/gltrace_hooks.cpp \
-    src/gltrace_transport.cpp \
-    $(call all-proto-files-under, proto)
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH) \
-    $(LOCAL_PATH)/../ \
-    external
-
-LOCAL_STATIC_LIBRARIES := liblzf
-LOCAL_SHARED_LIBRARIES := libcutils libutils liblog
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := lite
-
-LOCAL_CFLAGS += -DLOG_TAG=\"libGLES_trace\"
-
-# we need to access the private Bionic header <bionic_tls.h>
-LOCAL_C_INCLUDES += bionic/libc/private
-
-LOCAL_MODULE:= libGLES_trace
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/opengl/libs/GLES_trace/DESIGN.txt b/opengl/libs/GLES_trace/DESIGN.txt
deleted file mode 100644
index 72a2e15..0000000
--- a/opengl/libs/GLES_trace/DESIGN.txt
+++ /dev/null
@@ -1,79 +0,0 @@
-Design of the GLES Tracing Library
-
-Code Runtime Behavior:
-
-    Initialization:
-    
-    egl_display_t::initialize() calls initEglTraceLevel() to figure out whether tracing should be
-    enabled. Currently, the shell properties "debug.egl.trace" and "debug.egl.debug_proc" together
-    control whether tracing should be enabled for a certain process. If tracing is enabled, this
-    calls GLTrace_start() to start the trace server.
-    
-    egl_display_t::initialize() then calls setGLHooksThreadSpecific() where we set the thread
-    specific gl_hooks structure to point to the trace implementation. From this point on, every
-    GLES call is redirected to the trace implementation.
-    
-    Application runtime:
-
-    While the application is running, all its GLES calls are directly routed to their corresponding
-    trace implementation.
-
-    For EGL calls, the trace library provides a bunch of functions that must be explicitly called
-    from the EGL library. These functions are declared in glestrace.h
-
-    Application shutdown:
-
-    Currently, the application is killed when the user stops tracing from the frontend GUI. We need
-    to explore if a more graceful method of stopping the application, or detaching tracing from the
-    application is required.
-
-
-Enabling tracing while the application is running:
-
-    In order to allow tracing of an already running application, we allow DdmServer to enable
-    OpenGL tracing. In such a case, the application already has its GL hooks set up to point to the
-    real GL implementation, and we need to switch them to point to the trace implementation.
-
-    This is achieved by checking whether tracing should be enabled at every eglSwap call.
-    (Note: We were already checking for tracing at every eglSwap, the only change now is that
-    the tracing could actually be ON/OFF at runtime - earlier it was set once and never changed).
-
-    If eglSwap detects that tracing should be enabled now, then it performs the following steps:
-        - switch the gl hooks to point to the trace implementation.
-        - call trace eglMakeCurrent to indicate that there is now a new context that is current.
-        - continue on with tracing the eglSwap call.
-    This switches the hooks to point to the trace implementation only for the current context.
-    But the other contexts have their gl hooks updated when they perform eglMakeCurrent.
-
-    The GLTrace version of eglMakeCurrent now has to be updated to allow switching to a context
-    it may not know of. In such a case, it creates a context matching the version that it is now
-    switching to.
-
-Disabling tracing:
-
-    We disable tracing under two conditions:
-        - stop tracing request from DdmServer
-        - gltrace transport gets disconnected from the host.
-    In either case, both actions simply disable the tracing flag. The current context gets its
-    gl hooks restored in the next eglSwap, and the other traced contexts get their gl hooks
-    restored when they perform a eglMakeCurrent.
-
-Code Structure:
-
-    glestrace.h declares all the hooks exposed by libglestrace. These are used by EGL/egl.cpp and
-    EGL/eglApi.cpp to initialize the trace library, and to inform the library of EGL calls.
-
-    All GL calls are present in GLES_Trace/src/gltrace_api.cpp. This file is generated by the
-    GLES_Trace/src/genapi.py script. The structure of all the functions looks like this:
-
-            void GLTrace_glFunction(args) {
-                // declare a protobuf
-                // copy arguments into the protobuf
-                // call the original GLES function
-                // if there is a return value, save it into the protobuf
-                // fixup the protobuf if necessary
-                // transport the protobuf to the host
-            }
-
-    The fixupGLMessage() call does any custom processing of the protobuf based on the GLES call.
-    This typically amounts to copying the data corresponding to input or output pointers.
diff --git a/opengl/libs/GLES_trace/dev.make b/opengl/libs/GLES_trace/dev.make
deleted file mode 100644
index 3405d8e..0000000
--- a/opengl/libs/GLES_trace/dev.make
+++ /dev/null
@@ -1,9 +0,0 @@
-## NOTE
-## This file is used for development purposes only. It is not used by the build system.
-
-sync:
-	adb root
-	adb remount
-	adb shell stop
-	adb sync
-	adb shell start
diff --git a/opengl/libs/GLES_trace/proto/gltrace.proto b/opengl/libs/GLES_trace/proto/gltrace.proto
deleted file mode 100644
index 0344787..0000000
--- a/opengl/libs/GLES_trace/proto/gltrace.proto
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * 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.
- */
-
-package android.gltrace;
-
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.android.ide.eclipse.gltrace";
-option java_outer_classname = "GLProtoBuf";
-
-message GLMessage {
-    enum Function {
-        option allow_alias = true;
-
-        glActiveTexture = 0;
-        glAlphaFunc = 1;
-        glAlphaFuncx = 2;
-        glAlphaFuncxOES = 3;
-        glAttachShader = 4;
-        glBeginPerfMonitorAMD = 5;
-        glBindAttribLocation = 6;
-        glBindBuffer = 7;
-        glBindFramebuffer = 8;
-        glBindFramebufferOES = 9;
-        glBindRenderbuffer = 10;
-        glBindRenderbufferOES = 11;
-        glBindTexture = 12;
-        glBindVertexArrayOES = 13;
-        glBlendColor = 14;
-        glBlendEquation = 15;
-        glBlendEquationOES = 16;
-        glBlendEquationSeparate = 17;
-        glBlendEquationSeparateOES = 18;
-        glBlendFunc = 19;
-        glBlendFuncSeparate = 20;
-        glBlendFuncSeparateOES = 21;
-        glBufferData = 22;
-        glBufferSubData = 23;
-        glCheckFramebufferStatus = 24;
-        glCheckFramebufferStatusOES = 25;
-        glClearColor = 26;
-        glClearColorx = 27;
-        glClearColorxOES = 28;
-        glClearDepthf = 29;
-        glClearDepthfOES = 30;
-        glClearDepthx = 31;
-        glClearDepthxOES = 32;
-        glClear = 33;
-        glClearStencil = 34;
-        glClientActiveTexture = 35;
-        glClipPlanef = 36;
-        glClipPlanefIMG = 37;
-        glClipPlanefOES = 38;
-        glClipPlanex = 39;
-        glClipPlanexIMG = 40;
-        glClipPlanexOES = 41;
-        glColor4f = 42;
-        glColor4ub = 43;
-        glColor4x = 44;
-        glColor4xOES = 45;
-        glColorMask = 46;
-        glColorPointer = 47;
-        glCompileShader = 48;
-        glCompressedTexImage2D = 49;
-        glCompressedTexImage3DOES = 50;
-        glCompressedTexSubImage2D = 51;
-        glCompressedTexSubImage3DOES = 52;
-        glCopyTexImage2D = 53;
-        glCopyTexSubImage2D = 54;
-        glCopyTexSubImage3DOES = 55;
-        glCoverageMaskNV = 56;
-        glCoverageOperationNV = 57;
-        glCreateProgram = 58;
-        glCreateShader = 59;
-        glCullFace = 60;
-        glCurrentPaletteMatrixOES = 61;
-        glDeleteBuffers = 62;
-        glDeleteFencesNV = 63;
-        glDeleteFramebuffers = 64;
-        glDeleteFramebuffersOES = 65;
-        glDeletePerfMonitorsAMD = 66;
-        glDeleteProgram = 67;
-        glDeleteRenderbuffers = 68;
-        glDeleteRenderbuffersOES = 69;
-        glDeleteShader = 70;
-        glDeleteTextures = 71;
-        glDeleteVertexArraysOES = 72;
-        glDepthFunc = 73;
-        glDepthMask = 74;
-        glDepthRangef = 75;
-        glDepthRangefOES = 76;
-        glDepthRangex = 77;
-        glDepthRangexOES = 78;
-        glDetachShader = 79;
-        glDisableClientState = 80;
-        glDisableDriverControlQCOM = 81;
-        glDisable = 82;
-        glDisableVertexAttribArray = 83;
-        glDiscardFramebufferEXT = 84;
-        glDrawArrays = 85;
-        glDrawElements = 86;
-        glDrawTexfOES = 87;
-        glDrawTexfvOES = 88;
-        glDrawTexiOES = 89;
-        glDrawTexivOES = 90;
-        glDrawTexsOES = 91;
-        glDrawTexsvOES = 92;
-        glDrawTexxOES = 93;
-        glDrawTexxvOES = 94;
-        glEGLImageTargetRenderbufferStorageOES = 95;
-        glEGLImageTargetTexture2DOES = 96;
-        glEnableClientState = 97;
-        glEnableDriverControlQCOM = 98;
-        glEnable = 99;
-        glEnableVertexAttribArray = 100;
-        glEndPerfMonitorAMD = 101;
-        glEndTilingQCOM = 102;
-        glExtGetBufferPointervQCOM = 103;
-        glExtGetBuffersQCOM = 104;
-        glExtGetFramebuffersQCOM = 105;
-        glExtGetProgramBinarySourceQCOM = 106;
-        glExtGetProgramsQCOM = 107;
-        glExtGetRenderbuffersQCOM = 108;
-        glExtGetShadersQCOM = 109;
-        glExtGetTexLevelParameterivQCOM = 110;
-        glExtGetTexSubImageQCOM = 111;
-        glExtGetTexturesQCOM = 112;
-        glExtIsProgramBinaryQCOM = 113;
-        glExtTexObjectStateOverrideiQCOM = 114;
-        glFinishFenceNV = 115;
-        glFinish = 116;
-        glFlush = 117;
-        glFogf = 118;
-        glFogfv = 119;
-        glFogx = 120;
-        glFogxOES = 121;
-        glFogxv = 122;
-        glFogxvOES = 123;
-        glFramebufferRenderbuffer = 124;
-        glFramebufferRenderbufferOES = 125;
-        glFramebufferTexture2D = 126;
-        glFramebufferTexture2DMultisampleIMG = 127;
-        glFramebufferTexture2DOES = 128;
-        glFramebufferTexture3DOES = 129;
-        glFrontFace = 130;
-        glFrustumf = 131;
-        glFrustumfOES = 132;
-        glFrustumx = 133;
-        glFrustumxOES = 134;
-        glGenBuffers = 135;
-        glGenerateMipmap = 136;
-        glGenerateMipmapOES = 137;
-        glGenFencesNV = 138;
-        glGenFramebuffers = 139;
-        glGenFramebuffersOES = 140;
-        glGenPerfMonitorsAMD = 141;
-        glGenRenderbuffers = 142;
-        glGenRenderbuffersOES = 143;
-        glGenTextures = 144;
-        glGenVertexArraysOES = 145;
-        glGetActiveAttrib = 146;
-        glGetActiveUniform = 147;
-        glGetAttachedShaders = 148;
-        glGetAttribLocation = 149;
-        glGetBooleanv = 150;
-        glGetBufferParameteriv = 151;
-        glGetBufferPointervOES = 152;
-        glGetClipPlanef = 153;
-        glGetClipPlanefOES = 154;
-        glGetClipPlanex = 155;
-        glGetClipPlanexOES = 156;
-        glGetDriverControlsQCOM = 157;
-        glGetDriverControlStringQCOM = 158;
-        glGetError = 159;
-        glGetFenceivNV = 160;
-        glGetFixedv = 161;
-        glGetFixedvOES = 162;
-        glGetFloatv = 163;
-        glGetFramebufferAttachmentParameteriv = 164;
-        glGetFramebufferAttachmentParameterivOES = 165;
-        glGetIntegerv = 166;
-        glGetLightfv = 167;
-        glGetLightxv = 168;
-        glGetLightxvOES = 169;
-        glGetMaterialfv = 170;
-        glGetMaterialxv = 171;
-        glGetMaterialxvOES = 172;
-        glGetPerfMonitorCounterDataAMD = 173;
-        glGetPerfMonitorCounterInfoAMD = 174;
-        glGetPerfMonitorCountersAMD = 175;
-        glGetPerfMonitorCounterStringAMD = 176;
-        glGetPerfMonitorGroupsAMD = 177;
-        glGetPerfMonitorGroupStringAMD = 178;
-        glGetPointerv = 179;
-        glGetProgramBinaryOES = 180;
-        glGetProgramInfoLog = 181;
-        glGetProgramiv = 182;
-        glGetRenderbufferParameteriv = 183;
-        glGetRenderbufferParameterivOES = 184;
-        glGetShaderInfoLog = 185;
-        glGetShaderiv = 186;
-        glGetShaderPrecisionFormat = 187;
-        glGetShaderSource = 188;
-        glGetString = 189;
-        glGetTexEnvfv = 190;
-        glGetTexEnviv = 191;
-        glGetTexEnvxv = 192;
-        glGetTexEnvxvOES = 193;
-        glGetTexGenfvOES = 194;
-        glGetTexGenivOES = 195;
-        glGetTexGenxvOES = 196;
-        glGetTexParameterfv = 197;
-        glGetTexParameteriv = 198;
-        glGetTexParameterxv = 199;
-        glGetTexParameterxvOES = 200;
-        glGetUniformfv = 201;
-        glGetUniformiv = 202;
-        glGetUniformLocation = 203;
-        glGetVertexAttribfv = 204;
-        glGetVertexAttribiv = 205;
-        glGetVertexAttribPointerv = 206;
-        glHint = 207;
-        glIsBuffer = 208;
-        glIsEnabled = 209;
-        glIsFenceNV = 210;
-        glIsFramebuffer = 211;
-        glIsFramebufferOES = 212;
-        glIsProgram = 213;
-        glIsRenderbuffer = 214;
-        glIsRenderbufferOES = 215;
-        glIsShader = 216;
-        glIsTexture = 217;
-        glIsVertexArrayOES = 218;
-        glLightf = 219;
-        glLightfv = 220;
-        glLightModelf = 221;
-        glLightModelfv = 222;
-        glLightModelx = 223;
-        glLightModelxOES = 224;
-        glLightModelxv = 225;
-        glLightModelxvOES = 226;
-        glLightx = 227;
-        glLightxOES = 228;
-        glLightxv = 229;
-        glLightxvOES = 230;
-        glLineWidth = 231;
-        glLineWidthx = 232;
-        glLineWidthxOES = 233;
-        glLinkProgram = 234;
-        glLoadIdentity = 235;
-        glLoadMatrixf = 236;
-        glLoadMatrixx = 237;
-        glLoadMatrixxOES = 238;
-        glLoadPaletteFromModelViewMatrixOES = 239;
-        glLogicOp = 240;
-        glMapBufferOES = 241;
-        glMaterialf = 242;
-        glMaterialfv = 243;
-        glMaterialx = 244;
-        glMaterialxOES = 245;
-        glMaterialxv = 246;
-        glMaterialxvOES = 247;
-        glMatrixIndexPointerOES = 248;
-        glMatrixMode = 249;
-        glMultiDrawArraysEXT = 250;
-        glMultiDrawElementsEXT = 251;
-        glMultiTexCoord4f = 252;
-        glMultiTexCoord4x = 253;
-        glMultiTexCoord4xOES = 254;
-        glMultMatrixf = 255;
-        glMultMatrixx = 256;
-        glMultMatrixxOES = 257;
-        glNormal3f = 258;
-        glNormal3x = 259;
-        glNormal3xOES = 260;
-        glNormalPointer = 261;
-        glOrthof = 262;
-        glOrthofOES = 263;
-        glOrthox = 264;
-        glOrthoxOES = 265;
-        glPixelStorei = 266;
-        glPointParameterf = 267;
-        glPointParameterfv = 268;
-        glPointParameterx = 269;
-        glPointParameterxOES = 270;
-        glPointParameterxv = 271;
-        glPointParameterxvOES = 272;
-        glPointSize = 273;
-        glPointSizePointerOES = 274;
-        glPointSizex = 275;
-        glPointSizexOES = 276;
-        glPolygonOffset = 277;
-        glPolygonOffsetx = 278;
-        glPolygonOffsetxOES = 279;
-        glPopMatrix = 280;
-        glProgramBinaryOES = 281;
-        glPushMatrix = 282;
-        glQueryMatrixxOES = 283;
-        glReadPixels = 284;
-        glReleaseShaderCompiler = 285;
-        glRenderbufferStorage = 286;
-        glRenderbufferStorageMultisampleIMG = 287;
-        glRenderbufferStorageOES = 288;
-        glRotatef = 289;
-        glRotatex = 290;
-        glRotatexOES = 291;
-        glSampleCoverage = 292;
-        glSampleCoveragex = 293;
-        glSampleCoveragexOES = 294;
-        glScalef = 295;
-        glScalex = 296;
-        glScalexOES = 297;
-        glScissor = 298;
-        glSelectPerfMonitorCountersAMD = 299;
-        glSetFenceNV = 300;
-        glShadeModel = 301;
-        glShaderBinary = 302;
-        glShaderSource = 303;
-        glStartTilingQCOM = 304;
-        glStencilFunc = 305;
-        glStencilFuncSeparate = 306;
-        glStencilMask = 307;
-        glStencilMaskSeparate = 308;
-        glStencilOp = 309;
-        glStencilOpSeparate = 310;
-        glTestFenceNV = 311;
-        glTexCoordPointer = 312;
-        glTexEnvf = 313;
-        glTexEnvfv = 314;
-        glTexEnvi = 315;
-        glTexEnviv = 316;
-        glTexEnvx = 317;
-        glTexEnvxOES = 318;
-        glTexEnvxv = 319;
-        glTexEnvxvOES = 320;
-        glTexGenfOES = 321;
-        glTexGenfvOES = 322;
-        glTexGeniOES = 323;
-        glTexGenivOES = 324;
-        glTexGenxOES = 325;
-        glTexGenxvOES = 326;
-        glTexImage2D = 327;
-        glTexImage3DOES = 328;
-        glTexParameterf = 329;
-        glTexParameterfv = 330;
-        glTexParameteri = 331;
-        glTexParameteriv = 332;
-        glTexParameterx = 333;
-        glTexParameterxOES = 334;
-        glTexParameterxv = 335;
-        glTexParameterxvOES = 336;
-        glTexSubImage2D = 337;
-        glTexSubImage3DOES = 338;
-        glTranslatef = 339;
-        glTranslatex = 340;
-        glTranslatexOES = 341;
-        glUniform1f = 342;
-        glUniform1fv = 343;
-        glUniform1i = 344;
-        glUniform1iv = 345;
-        glUniform2f = 346;
-        glUniform2fv = 347;
-        glUniform2i = 348;
-        glUniform2iv = 349;
-        glUniform3f = 350;
-        glUniform3fv = 351;
-        glUniform3i = 352;
-        glUniform3iv = 353;
-        glUniform4f = 354;
-        glUniform4fv = 355;
-        glUniform4i = 356;
-        glUniform4iv = 357;
-        glUniformMatrix2fv = 358;
-        glUniformMatrix3fv = 359;
-        glUniformMatrix4fv = 360;
-        glUnmapBufferOES = 361;
-        glUseProgram = 362;
-        glValidateProgram = 363;
-        glVertexAttrib1f = 364;
-        glVertexAttrib1fv = 365;
-        glVertexAttrib2f = 366;
-        glVertexAttrib2fv = 367;
-        glVertexAttrib3f = 368;
-        glVertexAttrib3fv = 369;
-        glVertexAttrib4f = 370;
-        glVertexAttrib4fv = 371;
-        glVertexAttribPointer = 372;
-        glVertexPointer = 373;
-        glViewport = 374;
-        glWeightPointerOES = 375;
-        glReadBuffer = 376;
-        glDrawRangeElements = 377;
-        glTexImage3D = 378;
-        glTexSubImage3D = 379;
-        glCopyTexSubImage3D = 380;
-        glCompressedTexImage3D = 381;
-        glCompressedTexSubImage3D = 382;
-        glGenQueries = 383;
-        glDeleteQueries = 384;
-        glIsQuery = 385;
-        glBeginQuery = 386;
-        glEndQuery = 387;
-        glGetQueryiv = 388;
-        glGetQueryObjectuiv = 389;
-        glUnmapBuffer = 390;
-        glGetBufferPointerv = 391;
-        glDrawBuffers = 392;
-        glUniformMatrix2x3fv = 393;
-        glUniformMatrix3x2fv = 394;
-        glUniformMatrix2x4fv = 395;
-        glUniformMatrix4x2fv = 396;
-        glUniformMatrix3x4fv = 397;
-        glUniformMatrix4x3fv = 398;
-        glBlitFramebuffer = 399;
-        glRenderbufferStorageMultisample = 400;
-        glFramebufferTextureLayer = 401;
-        glMapBufferRange = 402;
-        glFlushMappedBufferRange = 403;
-        glBindVertexArray = 404;
-        glDeleteVertexArrays = 405;
-        glGenVertexArrays = 406;
-        glIsVertexArray = 407;
-        glGetIntegeri_v = 408;
-        glBeginTransformFeedback = 409;
-        glEndTransformFeedback = 410;
-        glBindBufferRange = 411;
-        glBindBufferBase = 412;
-        glTransformFeedbackVaryings = 413;
-        glGetTransformFeedbackVarying = 414;
-        glVertexAttribIPointer = 415;
-        glGetVertexAttribIiv = 416;
-        glGetVertexAttribIuiv = 417;
-        glVertexAttribI4i = 418;
-        glVertexAttribI4ui = 419;
-        glVertexAttribI4iv = 420;
-        glVertexAttribI4uiv = 421;
-        glGetUniformuiv = 422;
-        glGetFragDataLocation = 423;
-        glUniform1ui = 424;
-        glUniform2ui = 425;
-        glUniform3ui = 426;
-        glUniform4ui = 427;
-        glUniform1uiv = 428;
-        glUniform2uiv = 429;
-        glUniform3uiv = 430;
-        glUniform4uiv = 431;
-        glClearBufferiv = 432;
-        glClearBufferuiv = 433;
-        glClearBufferfv = 434;
-        glClearBufferfi = 435;
-        glGetStringi = 436;
-        glCopyBufferSubData = 437;
-        glGetUniformIndices = 438;
-        glGetActiveUniformsiv = 439;
-        glGetUniformBlockIndex = 440;
-        glGetActiveUniformBlockiv = 441;
-        glGetActiveUniformBlockName = 442;
-        glUniformBlockBinding = 443;
-        glDrawArraysInstanced = 444;
-        glDrawElementsInstanced = 445;
-        glFenceSync = 446;
-        glIsSync = 447;
-        glDeleteSync = 448;
-        glClientWaitSync = 449;
-        glWaitSync = 450;
-        glGetInteger64v = 451;
-        glGetSynciv = 452;
-        glGetInteger64i_v = 453;
-        glGetBufferParameteri64v = 454;
-        glGenSamplers = 455;
-        glDeleteSamplers = 456;
-        glIsSampler = 457;
-        glBindSampler = 458;
-        glSamplerParameteri = 459;
-        glSamplerParameteriv = 460;
-        glSamplerParameterf = 461;
-        glSamplerParameterfv = 462;
-        glGetSamplerParameteriv = 463;
-        glGetSamplerParameterfv = 464;
-        glVertexAttribDivisor = 465;
-        glBindTransformFeedback = 466;
-        glDeleteTransformFeedbacks = 467;
-        glGenTransformFeedbacks = 468;
-        glIsTransformFeedback = 469;
-        glPauseTransformFeedback = 470;
-        glResumeTransformFeedback = 471;
-        glGetProgramBinary = 472;
-        glProgramBinary = 473;
-        glProgramParameteri = 474;
-        glInvalidateFramebuffer = 475;
-        glInvalidateSubFramebuffer = 476;
-        glTexStorage2D = 477;
-        glTexStorage3D = 478;
-        glGetInternalformativ = 479;
-        glBeginPerfQueryINTEL = 480;
-        glCreatePerfQueryINTEL = 481;
-        glDeletePerfQueryINTEL = 482;
-        glEndPerfQueryINTEL = 483;
-        glGetFirstPerfQueryIdINTEL = 484;
-        glGetNextPerfQueryIdINTEL = 485;
-        glGetPerfCounterInfoINTEL = 486;
-        glGetPerfQueryDataINTEL = 487;
-        glGetPerfQueryIdByNameINTEL = 488;
-        glGetPerfQueryInfoINTEL = 489;
-        glBlendBarrierKHR = 490;
-        glBlendBarrierNV = 491;
-        glBlendParameteriNV = 492;
-        glBlitFramebufferNV = 493;
-        glFenceSyncAPPLE = 494;
-        glIsSyncAPPLE = 495;
-        glDeleteSyncAPPLE = 496;
-        glClientWaitSyncAPPLE = 497;
-        glWaitSyncAPPLE = 498;
-        glGetInteger64vAPPLE = 499;
-        glGetSyncivAPPLE = 500;
-        glCopyBufferSubDataNV = 501;
-        glActiveShaderProgramEXT = 502;
-        glAlphaFuncQCOM = 503;
-        glBeginQueryEXT = 504;
-        glBindProgramPipelineEXT = 505;
-        glBlitFramebufferANGLE = 506;
-        glCreateShaderProgramvEXT = 507;
-        glDeleteProgramPipelinesEXT = 508;
-        glDeleteQueriesEXT = 509;
-        glDrawBuffersNV = 510;
-        glEndQueryEXT = 511;
-        glFramebufferTexture2DMultisampleEXT = 512;
-        glGenProgramPipelinesEXT = 513;
-        glGenQueriesEXT = 514;
-        glGetGraphicsResetStatusEXT = 515;
-        glGetObjectLabelEXT = 516;
-        glGetProgramPipelineInfoLogEXT = 517;
-        glGetProgramPipelineivEXT = 518;
-        glGetQueryObjectuivEXT = 519;
-        glGetQueryivEXT = 520;
-        glGetnUniformfvEXT = 521;
-        glGetnUniformivEXT = 521;
-        glInsertEventMarkerEXT = 522;
-        glIsProgramPipelineEXT = 523;
-        glIsQueryEXT = 524;
-        glLabelObjectEXT = 525;
-        glPopGroupMarkerEXT = 526;
-        glProgramParameteriEXT = 527;
-        glProgramUniform1fEXT = 528;
-        glProgramUniform1fvEXT = 529;
-        glProgramUniform1iEXT = 530;
-        glProgramUniform1ivEXT = 531;
-        glProgramUniform2fEXT = 532;
-        glProgramUniform2fvEXT = 533;
-        glProgramUniform2iEXT = 534;
-        glProgramUniform2ivEXT = 535;
-        glProgramUniform3fEXT = 536;
-        glProgramUniform3fvEXT = 537;
-        glProgramUniform3iEXT = 538;
-        glProgramUniform3ivEXT = 539;
-        glProgramUniform4fEXT = 540;
-        glProgramUniform4fvEXT = 541;
-        glProgramUniform4iEXT = 542;
-        glProgramUniform4ivEXT = 543;
-        glProgramUniformMatrix2fvEXT = 544;
-        glProgramUniformMatrix3fvEXT = 545;
-        glProgramUniformMatrix4fvEXT = 546;
-        glPushGroupMarkerEXT = 547;
-        glReadBufferNV = 548;
-        glReadnPixelsEXT = 549;
-        glRenderbufferStorageMultisampleANGLE = 550;
-        glRenderbufferStorageMultisampleAPPLE = 551;
-        glRenderbufferStorageMultisampleEXT = 552;
-        glResolveMultisampleFramebufferAPPLE = 553;
-        glTexStorage1DEXT = 554;
-        glTexStorage2DEXT = 555;
-        glTexStorage3DEXT = 556;
-        glTextureStorage1DEXT = 557;
-        glTextureStorage2DEXT = 558;
-        glTextureStorage3DEXT = 559;
-        glUseProgramStagesEXT = 560;
-        glValidateProgramPipelineEXT = 561;
-        glCopyTextureLevelsAPPLE = 562;
-        glDebugMessageControlKHR = 563;
-        glDebugMessageInsertKHR = 564;
-        glDebugMessageCallbackKHR = 565;
-        glGetDebugMessageLogKHR = 566;
-        glPushDebugGroupKHR = 567;
-        glPopDebugGroupKHR = 568;
-        glObjectLabelKHR = 569;
-        glGetObjectLabelKHR = 570;
-        glObjectPtrLabelKHR = 571;
-        glGetObjectPtrLabelKHR = 572;
-        glGetPointervKHR = 573;
-        glDrawArraysInstancedANGLE = 574;
-        glDrawElementsInstancedANGLE = 575;
-        glVertexAttribDivisorANGLE = 576;
-        glDrawArraysInstancedEXT = 577;
-        glDrawElementsInstancedEXT = 578;
-        glVertexAttribDivisorEXT = 579;
-        glDrawArraysInstancedNV = 580;
-        glDrawElementsInstancedNV = 581;
-        glVertexAttribDivisorNV = 582;
-        glDrawBuffersEXT = 583;
-        glReadBufferIndexedEXT = 584;
-        glDrawBuffersIndexedEXT = 585;
-        glGetIntegeri_vEXT = 586;
-        glMapBufferRangeEXT = 587;
-        glFlushMappedBufferRangeEXT = 588;
-        glQueryCounterEXT = 589;
-        glGetQueryObjecti64vEXT = 590;
-        glGetQueryObjectivEXT = 591;
-        glGetQueryObjectui64vEXT = 592;
-        glGetTranslatedShaderSourceANGLE = 593;
-        glMinSampleShadingOES = 594;
-        glMultiTexCoord1bOES = 595;
-        glMultiTexCoord1bvOES = 596;
-        glMultiTexCoord2bOES = 597;
-        glMultiTexCoord2bvOES = 598;
-        glMultiTexCoord3bOES = 599;
-        glMultiTexCoord3bvOES = 600;
-        glMultiTexCoord4bOES = 601;
-        glMultiTexCoord4bvOES = 602;
-        glTexCoord1bOES = 603;
-        glTexCoord1bvOES = 604;
-        glTexCoord2bOES = 605;
-        glTexCoord2bvOES = 606;
-        glTexCoord3bOES = 607;
-        glTexCoord3bvOES = 608;
-        glTexCoord4bOES = 609;
-        glTexCoord4bvOES = 610;
-        glVertex2bOES = 611;
-        glVertex2bvOES = 612;
-        glVertex3bOES = 613;
-        glVertex3bvOES = 614;
-        glVertex4bOES = 615;
-        glVertex4bvOES = 616;
-        glProgramUniform1uiEXT = 617;
-        glProgramUniform2uiEXT = 618;
-        glProgramUniform3uiEXT = 619;
-        glProgramUniform4uiEXT = 620;
-        glProgramUniform1uivEXT = 621;
-        glProgramUniform2uivEXT = 622;
-        glProgramUniform3uivEXT = 623;
-        glProgramUniform4uivEXT = 624;
-        glProgramUniformMatrix2x3fvEXT = 625;
-        glProgramUniformMatrix3x2fvEXT = 626;
-        glProgramUniformMatrix2x4fvEXT = 627;
-        glProgramUniformMatrix4x2fvEXT = 628;
-        glProgramUniformMatrix3x4fvEXT = 629;
-        glProgramUniformMatrix4x3fvEXT = 630;
-        glRenderbufferStorageMultisampleNV = 631;
-        glSampleCoverageOES = 632;
-        glTexStorage3DMultisampleOES = 633;
-        glUniformMatrix2x3fvNV = 634;
-        glUniformMatrix3x2fvNV = 635;
-        glUniformMatrix2x4fvNV = 636;
-        glUniformMatrix4x2fvNV = 637;
-        glUniformMatrix3x4fvNV = 638;
-        glUniformMatrix4x3fvNV = 639;
-        glActiveShaderProgram = 640;
-        glBindImageTexture = 641;
-        glBindProgramPipeline = 642;
-        glBindVertexBuffer = 643;
-        glCreateShaderProgramv = 644;
-        glDeleteProgramPipelines = 645;
-        glDispatchCompute = 646;
-        glDispatchComputeIndirect = 647;
-        glDrawArraysIndirect = 648;
-        glDrawElementsIndirect = 649;
-        glFramebufferParameteri = 650;
-        glGenProgramPipelines = 651;
-        glGetBooleani_v = 652;
-        glGetFramebufferParameteriv = 653;
-        glGetMultisamplefv = 654;
-        glGetProgramInterfaceiv = 655;
-        glGetProgramPipelineInfoLog = 656;
-        glGetProgramPipelineiv = 657;
-        glGetProgramResourceIndex = 658;
-        glGetProgramResourceLocation = 659;
-        glGetProgramResourceName = 660;
-        glGetProgramResourceiv = 661;
-        glGetTexLevelParameterfv = 662;
-        glGetTexLevelParameteriv = 663;
-        glIsProgramPipeline = 664;
-        glMemoryBarrier = 665;
-        glMemoryBarrierByRegion = 666;
-        glProgramUniform1f = 667;
-        glProgramUniform1fv = 668;
-        glProgramUniform1i = 669;
-        glProgramUniform1iv = 670;
-        glProgramUniform1ui = 671;
-        glProgramUniform1uiv = 672;
-        glProgramUniform2f = 673;
-        glProgramUniform2fv = 674;
-        glProgramUniform2i = 675;
-        glProgramUniform2iv = 676;
-        glProgramUniform2ui = 677;
-        glProgramUniform2uiv = 678;
-        glProgramUniform3f = 679;
-        glProgramUniform3fv = 680;
-        glProgramUniform3i = 681;
-        glProgramUniform3iv = 682;
-        glProgramUniform3ui = 683;
-        glProgramUniform3uiv = 684;
-        glProgramUniform4f = 685;
-        glProgramUniform4fv = 686;
-        glProgramUniform4i = 687;
-        glProgramUniform4iv = 688;
-        glProgramUniform4ui = 689;
-        glProgramUniform4uiv = 690;
-        glProgramUniformMatrix2fv = 691;
-        glProgramUniformMatrix2x3fv = 692;
-        glProgramUniformMatrix2x4fv = 693;
-        glProgramUniformMatrix3fv = 694;
-        glProgramUniformMatrix3x2fv = 695;
-        glProgramUniformMatrix3x4fv = 696;
-        glProgramUniformMatrix4fv = 697;
-        glProgramUniformMatrix4x2fv = 698;
-        glProgramUniformMatrix4x3fv = 699;
-        glSampleMaski = 700;
-        glTexStorage2DMultisample = 701;
-        glUseProgramStages = 702;
-        glValidateProgramPipeline = 703;
-        glVertexAttribBinding = 704;
-        glVertexAttribFormat = 705;
-        glVertexAttribIFormat = 706;
-        glVertexBindingDivisor = 707;
-        glBlendEquationSeparateiEXT = 708;
-        glBlendEquationiEXT = 709;
-        glBlendFuncSeparateiEXT = 710;
-        glBlendFunciEXT = 711;
-        glColorMaskiEXT = 712;
-        glCopyImageSubDataEXT = 713;
-        glDisableiEXT = 714;
-        glEnableiEXT = 715;
-        glFramebufferTextureEXT = 716;
-        glGetSamplerParameterIivEXT = 717;
-        glGetSamplerParameterIuivEXT = 718;
-        glGetTexParameterIivEXT = 719;
-        glGetTexParameterIuivEXT = 720;
-        glIsEnablediEXT = 721;
-        glPatchParameteriEXT = 722;
-        glPrimitiveBoundingBoxEXT = 723;
-        glSamplerParameterIivEXT = 724;
-        glSamplerParameterIuivEXT = 725;
-        glTexBufferEXT = 726;
-        glTexBufferRangeEXT = 727;
-        glTexParameterIivEXT = 728;
-        glTexParameterIuivEXT = 729;
-        glTextureViewEXT = 730;
-
-        eglGetDisplay = 2000;
-        eglInitialize = 2001;
-        eglTerminate = 2002;
-        eglGetConfigs = 2003;
-        eglChooseConfig = 2004;
-        eglGetConfigAttrib = 2005;
-        eglCreateWindowSurface = 2006;
-        eglCreatePixmapSurface = 2007;
-        eglCreatePbufferSurface = 2008;
-        eglDestroySurface = 2009;
-        eglQuerySurface = 2010;
-        eglCreateContext = 2011;
-        eglDestroyContext = 2012;
-        eglMakeCurrent = 2013;
-        eglGetCurrentContext = 2014;
-        eglGetCurrentSurface = 2015;
-        eglGetCurrentDisplay = 2016;
-        eglQueryContext = 2017;
-        eglWaitGL = 2018;
-        eglWaitNative = 2019;
-        eglSwapBuffers = 2020;
-        eglCopyBuffers = 2021;
-        eglGetError = 2022;
-        eglQueryString = 2023;
-        eglGetProcAddress = 2024;
-        eglSurfaceAttrib = 2025;
-        eglBindTexImage = 2026;
-        eglReleaseTexImage = 2027;
-        eglSwapInterval = 2028;
-        eglBindAPI = 2029;
-        eglQueryAPI = 2030;
-        eglWaitClient = 2031;
-        eglReleaseThread = 2032;
-        eglCreatePbufferFromClientBuffer = 2033;
-        eglLockSurfaceKHR = 2034;
-        eglUnlockSurfaceKHR = 2035;
-        eglCreateImageKHR = 2036;
-        eglDestroyImageKHR = 2037;
-        eglCreateSyncKHR = 2038;
-        eglDestroySyncKHR = 2039;
-        eglClientWaitSyncKHR = 2040;
-        eglGetSyncAttribKHR = 2041;
-        eglSetSwapRectangleANDROID = 2042;
-        eglGetRenderBufferANDROID = 2043;
-        eglGetSystemTimeFrequencyNV = 2044;
-        eglGetSystemTimeNV = 2045;
-
-        invalid = 3000;
-        glVertexAttribPointerData = 3001;
-    }
-
-    // A GL call's return data and arguments are formatted into this DataType
-    message DataType {
-        enum Type {
-            VOID = 1;       // GLvoid
-            CHAR = 2;       // GLchar
-            BYTE = 3;       // GLbyte, GLubyte
-            INT = 4;        // GLbitfield, GLshort, GLint, GLsizei, GLushort, GLuint, GLfixed
-            FLOAT = 5;      // GLfloat, GLclampf
-            BOOL = 6;       // GLboolean
-            ENUM = 7;       // GLenum
-            INT64 = 8;      // GLint64, GLuint64
-        };
-
-        required Type   type = 1 [default = VOID];
-        required bool   isArray = 2 [default = false];
-
-        repeated int32  intValue = 3;
-        repeated float  floatValue = 4;
-        repeated bytes  charValue = 5;
-        repeated bytes  rawBytes = 6;
-        repeated bool   boolValue = 7;
-        repeated int64  int64Value = 8;
-    }
-
-    message FrameBuffer {
-        required int32  width = 1;
-        required int32  height = 2;
-        repeated bytes  contents = 3;
-    }
-
-    required int32      context_id = 1;                     // GL context ID
-    required int64      start_time = 2;                     // time when call was invoked
-    required int32      duration = 3;                       // duration of the call (MONOTONIC TIME)
-
-    required Function   function = 4 [default = invalid];   // GL function called
-    repeated DataType   args = 5;                           // GL function's arguments
-    optional DataType   returnValue = 6;                    // GL function's return value
-
-    optional FrameBuffer fb = 7;                            // contents of the framebuffer
-
-    optional int32      threadtime = 8;                     // duration of the call (THREAD TIME)
-};
diff --git a/opengl/libs/GLES_trace/src/gltrace_api.cpp b/opengl/libs/GLES_trace/src/gltrace_api.cpp
deleted file mode 100644
index d83b9b4..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_api.cpp
+++ /dev/null
@@ -1,30963 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- *
- * THIS FILE WAS GENERATED BY A SCRIPT. DO NOT EDIT.
- */
-
-#include <cutils/log.h>
-#include <utils/Timers.h>
-
-#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
-#include "gltrace_context.h"
-#include "gltrace_fixup.h"
-#include "gltrace_transport.h"
-
-namespace android {
-namespace gltrace {
-
-// Definitions for GL2 APIs
-
-void GLTrace_glActiveTexture(GLenum texture) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glActiveTexture);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glActiveTexture(texture);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glAttachShader(GLuint program, GLuint shader) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glAttachShader);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glAttachShader(program, shader);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindAttribLocation(GLuint program, GLuint index, const GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindAttribLocation);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindAttribLocation(program, index, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindBuffer(GLenum target, GLuint buffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindBuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindBuffer(target, buffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindFramebuffer(GLenum target, GLuint framebuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindFramebuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument framebuffer
-    GLMessage_DataType *arg_framebuffer = glmsg.add_args();
-    arg_framebuffer->set_isarray(false);
-    arg_framebuffer->set_type(GLMessage::DataType::INT);
-    arg_framebuffer->add_intvalue(framebuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindFramebuffer(target, framebuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindRenderbuffer(GLenum target, GLuint renderbuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindRenderbuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument renderbuffer
-    GLMessage_DataType *arg_renderbuffer = glmsg.add_args();
-    arg_renderbuffer->set_isarray(false);
-    arg_renderbuffer->set_type(GLMessage::DataType::INT);
-    arg_renderbuffer->add_intvalue(renderbuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindRenderbuffer(target, renderbuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindTexture(GLenum target, GLuint texture) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindTexture);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindTexture(target, texture);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendColor);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::FLOAT);
-    arg_red->add_floatvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::FLOAT);
-    arg_green->add_floatvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::FLOAT);
-    arg_blue->add_floatvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::FLOAT);
-    arg_alpha->add_floatvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendColor(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendEquation(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendEquation);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendEquation(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendEquationSeparate);
-
-    // copy argument modeRGB
-    GLMessage_DataType *arg_modeRGB = glmsg.add_args();
-    arg_modeRGB->set_isarray(false);
-    arg_modeRGB->set_type(GLMessage::DataType::ENUM);
-    arg_modeRGB->add_intvalue((int)modeRGB);
-
-    // copy argument modeAlpha
-    GLMessage_DataType *arg_modeAlpha = glmsg.add_args();
-    arg_modeAlpha->set_isarray(false);
-    arg_modeAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_modeAlpha->add_intvalue((int)modeAlpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendEquationSeparate(modeRGB, modeAlpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendFunc(GLenum sfactor, GLenum dfactor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendFunc);
-
-    // copy argument sfactor
-    GLMessage_DataType *arg_sfactor = glmsg.add_args();
-    arg_sfactor->set_isarray(false);
-    arg_sfactor->set_type(GLMessage::DataType::ENUM);
-    arg_sfactor->add_intvalue((int)sfactor);
-
-    // copy argument dfactor
-    GLMessage_DataType *arg_dfactor = glmsg.add_args();
-    arg_dfactor->set_isarray(false);
-    arg_dfactor->set_type(GLMessage::DataType::ENUM);
-    arg_dfactor->add_intvalue((int)dfactor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendFunc(sfactor, dfactor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendFuncSeparate);
-
-    // copy argument sfactorRGB
-    GLMessage_DataType *arg_sfactorRGB = glmsg.add_args();
-    arg_sfactorRGB->set_isarray(false);
-    arg_sfactorRGB->set_type(GLMessage::DataType::ENUM);
-    arg_sfactorRGB->add_intvalue((int)sfactorRGB);
-
-    // copy argument dfactorRGB
-    GLMessage_DataType *arg_dfactorRGB = glmsg.add_args();
-    arg_dfactorRGB->set_isarray(false);
-    arg_dfactorRGB->set_type(GLMessage::DataType::ENUM);
-    arg_dfactorRGB->add_intvalue((int)dfactorRGB);
-
-    // copy argument sfactorAlpha
-    GLMessage_DataType *arg_sfactorAlpha = glmsg.add_args();
-    arg_sfactorAlpha->set_isarray(false);
-    arg_sfactorAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_sfactorAlpha->add_intvalue((int)sfactorAlpha);
-
-    // copy argument dfactorAlpha
-    GLMessage_DataType *arg_dfactorAlpha = glmsg.add_args();
-    arg_dfactorAlpha->set_isarray(false);
-    arg_dfactorAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_dfactorAlpha->add_intvalue((int)dfactorAlpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBufferData(GLenum target, GLsizeiptr size, const void * data, GLenum usage) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBufferData);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // copy argument usage
-    GLMessage_DataType *arg_usage = glmsg.add_args();
-    arg_usage->set_isarray(false);
-    arg_usage->set_type(GLMessage::DataType::ENUM);
-    arg_usage->add_intvalue((int)usage);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBufferData(target, size, data, usage);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBufferSubData);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBufferSubData(target, offset, size, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLenum GLTrace_glCheckFramebufferStatus(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCheckFramebufferStatus);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLenum retValue = glContext->hooks->gl.glCheckFramebufferStatus(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::ENUM);
-    rt->add_intvalue((int)retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glClear(GLbitfield mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClear);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClear(mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearColor);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::FLOAT);
-    arg_red->add_floatvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::FLOAT);
-    arg_green->add_floatvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::FLOAT);
-    arg_blue->add_floatvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::FLOAT);
-    arg_alpha->add_floatvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearColor(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearDepthf(GLfloat d) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearDepthf);
-
-    // copy argument d
-    GLMessage_DataType *arg_d = glmsg.add_args();
-    arg_d->set_isarray(false);
-    arg_d->set_type(GLMessage::DataType::FLOAT);
-    arg_d->add_floatvalue(d);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearDepthf(d);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearStencil(GLint s) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearStencil);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::INT);
-    arg_s->add_intvalue(s);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearStencil(s);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColorMask);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::BOOL);
-    arg_red->add_boolvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::BOOL);
-    arg_green->add_boolvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::BOOL);
-    arg_blue->add_boolvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::BOOL);
-    arg_alpha->add_boolvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColorMask(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompileShader(GLuint shader) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompileShader);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompileShader(shader);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompressedTexImage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // copy argument imageSize
-    GLMessage_DataType *arg_imageSize = glmsg.add_args();
-    arg_imageSize->set_isarray(false);
-    arg_imageSize->set_type(GLMessage::DataType::INT);
-    arg_imageSize->add_intvalue(imageSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompressedTexSubImage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument imageSize
-    GLMessage_DataType *arg_imageSize = glmsg.add_args();
-    arg_imageSize->set_isarray(false);
-    arg_imageSize->set_type(GLMessage::DataType::INT);
-    arg_imageSize->add_intvalue(imageSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyTexImage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyTexSubImage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLuint GLTrace_glCreateProgram(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCreateProgram);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glCreateProgram();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLuint GLTrace_glCreateShader(GLenum type) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCreateShader);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glCreateShader(type);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glCullFace(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCullFace);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCullFace(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteBuffers(GLsizei n, const GLuint * buffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteBuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument buffers
-    GLMessage_DataType *arg_buffers = glmsg.add_args();
-    arg_buffers->set_isarray(false);
-    arg_buffers->set_type(GLMessage::DataType::INT64);
-    arg_buffers->add_int64value((uintptr_t)buffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteBuffers(n, buffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) buffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteFramebuffers(GLsizei n, const GLuint * framebuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteFramebuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument framebuffers
-    GLMessage_DataType *arg_framebuffers = glmsg.add_args();
-    arg_framebuffers->set_isarray(false);
-    arg_framebuffers->set_type(GLMessage::DataType::INT64);
-    arg_framebuffers->add_int64value((uintptr_t)framebuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteFramebuffers(n, framebuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) framebuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteProgram(GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteProgram);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteProgram(program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteRenderbuffers(GLsizei n, const GLuint * renderbuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteRenderbuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument renderbuffers
-    GLMessage_DataType *arg_renderbuffers = glmsg.add_args();
-    arg_renderbuffers->set_isarray(false);
-    arg_renderbuffers->set_type(GLMessage::DataType::INT64);
-    arg_renderbuffers->add_int64value((uintptr_t)renderbuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteRenderbuffers(n, renderbuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) renderbuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteShader(GLuint shader) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteShader);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteShader(shader);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteTextures(GLsizei n, const GLuint * textures) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteTextures);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument textures
-    GLMessage_DataType *arg_textures = glmsg.add_args();
-    arg_textures->set_isarray(false);
-    arg_textures->set_type(GLMessage::DataType::INT64);
-    arg_textures->add_int64value((uintptr_t)textures);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteTextures(n, textures);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) textures,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDepthFunc(GLenum func) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDepthFunc);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDepthFunc(func);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDepthMask(GLboolean flag) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDepthMask);
-
-    // copy argument flag
-    GLMessage_DataType *arg_flag = glmsg.add_args();
-    arg_flag->set_isarray(false);
-    arg_flag->set_type(GLMessage::DataType::BOOL);
-    arg_flag->add_boolvalue(flag);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDepthMask(flag);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDepthRangef(GLfloat n, GLfloat f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDepthRangef);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::FLOAT);
-    arg_n->add_floatvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::FLOAT);
-    arg_f->add_floatvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDepthRangef(n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDetachShader(GLuint program, GLuint shader) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDetachShader);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDetachShader(program, shader);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDisable(GLenum cap) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDisable);
-
-    // copy argument cap
-    GLMessage_DataType *arg_cap = glmsg.add_args();
-    arg_cap->set_isarray(false);
-    arg_cap->set_type(GLMessage::DataType::ENUM);
-    arg_cap->add_intvalue((int)cap);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDisable(cap);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDisableVertexAttribArray(GLuint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDisableVertexAttribArray);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDisableVertexAttribArray(index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawArrays(GLenum mode, GLint first, GLsizei count) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawArrays);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument first
-    GLMessage_DataType *arg_first = glmsg.add_args();
-    arg_first->set_isarray(false);
-    arg_first->set_type(GLMessage::DataType::INT);
-    arg_first->add_intvalue(first);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawArrays(mode, first, count);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawElements(GLenum mode, GLsizei count, GLenum type, const void * indices) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawElements);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawElements(mode, count, type, indices);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEnable(GLenum cap) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEnable);
-
-    // copy argument cap
-    GLMessage_DataType *arg_cap = glmsg.add_args();
-    arg_cap->set_isarray(false);
-    arg_cap->set_type(GLMessage::DataType::ENUM);
-    arg_cap->add_intvalue((int)cap);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEnable(cap);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEnableVertexAttribArray(GLuint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEnableVertexAttribArray);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEnableVertexAttribArray(index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFinish(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFinish);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFinish();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFlush(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFlush);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFlush();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferRenderbuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument renderbuffertarget
-    GLMessage_DataType *arg_renderbuffertarget = glmsg.add_args();
-    arg_renderbuffertarget->set_isarray(false);
-    arg_renderbuffertarget->set_type(GLMessage::DataType::ENUM);
-    arg_renderbuffertarget->add_intvalue((int)renderbuffertarget);
-
-    // copy argument renderbuffer
-    GLMessage_DataType *arg_renderbuffer = glmsg.add_args();
-    arg_renderbuffer->set_isarray(false);
-    arg_renderbuffer->set_type(GLMessage::DataType::INT);
-    arg_renderbuffer->add_intvalue(renderbuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTexture2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument textarget
-    GLMessage_DataType *arg_textarget = glmsg.add_args();
-    arg_textarget->set_isarray(false);
-    arg_textarget->set_type(GLMessage::DataType::ENUM);
-    arg_textarget->add_intvalue((int)textarget);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTexture2D(target, attachment, textarget, texture, level);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFrontFace(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFrontFace);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFrontFace(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenBuffers(GLsizei n, GLuint * buffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenBuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument buffers
-    GLMessage_DataType *arg_buffers = glmsg.add_args();
-    arg_buffers->set_isarray(false);
-    arg_buffers->set_type(GLMessage::DataType::INT64);
-    arg_buffers->add_int64value((uintptr_t)buffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenBuffers(n, buffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) buffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenerateMipmap(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenerateMipmap);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenerateMipmap(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenFramebuffers(GLsizei n, GLuint * framebuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenFramebuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument framebuffers
-    GLMessage_DataType *arg_framebuffers = glmsg.add_args();
-    arg_framebuffers->set_isarray(false);
-    arg_framebuffers->set_type(GLMessage::DataType::INT64);
-    arg_framebuffers->add_int64value((uintptr_t)framebuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenFramebuffers(n, framebuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) framebuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenRenderbuffers(GLsizei n, GLuint * renderbuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenRenderbuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument renderbuffers
-    GLMessage_DataType *arg_renderbuffers = glmsg.add_args();
-    arg_renderbuffers->set_isarray(false);
-    arg_renderbuffers->set_type(GLMessage::DataType::INT64);
-    arg_renderbuffers->add_int64value((uintptr_t)renderbuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenRenderbuffers(n, renderbuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) renderbuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenTextures(GLsizei n, GLuint * textures) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenTextures);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument textures
-    GLMessage_DataType *arg_textures = glmsg.add_args();
-    arg_textures->set_isarray(false);
-    arg_textures->set_type(GLMessage::DataType::INT64);
-    arg_textures->add_int64value((uintptr_t)textures);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenTextures(n, textures);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) textures,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetActiveAttrib);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT64);
-    arg_size->add_int64value((uintptr_t)size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::INT64);
-    arg_type->add_int64value((uintptr_t)type);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetActiveAttrib(program, index, bufSize, length, size, type, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) size,
-        (void *) type,
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetActiveUniform);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT64);
-    arg_size->add_int64value((uintptr_t)size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::INT64);
-    arg_type->add_int64value((uintptr_t)type);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetActiveUniform(program, index, bufSize, length, size, type, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) size,
-        (void *) type,
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetAttachedShaders);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument maxCount
-    GLMessage_DataType *arg_maxCount = glmsg.add_args();
-    arg_maxCount->set_isarray(false);
-    arg_maxCount->set_type(GLMessage::DataType::INT);
-    arg_maxCount->add_intvalue(maxCount);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT64);
-    arg_count->add_int64value((uintptr_t)count);
-
-    // copy argument shaders
-    GLMessage_DataType *arg_shaders = glmsg.add_args();
-    arg_shaders->set_isarray(false);
-    arg_shaders->set_type(GLMessage::DataType::INT64);
-    arg_shaders->add_int64value((uintptr_t)shaders);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetAttachedShaders(program, maxCount, count, shaders);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) count,
-        (void *) shaders,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLint GLTrace_glGetAttribLocation(GLuint program, const GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetAttribLocation);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLint retValue = glContext->hooks->gl.glGetAttribLocation(program, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetBooleanv(GLenum pname, GLboolean * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetBooleanv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetBooleanv(pname, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetBufferParameteriv(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetBufferParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetBufferParameteriv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLenum GLTrace_glGetError(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetError);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLenum retValue = glContext->hooks->gl.glGetError();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::ENUM);
-    rt->add_intvalue((int)retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetFloatv(GLenum pname, GLfloat * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFloatv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFloatv(pname, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFramebufferAttachmentParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetIntegerv(GLenum pname, GLint * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetIntegerv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetIntegerv(pname, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramiv(GLuint program, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramiv(program, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramInfoLog);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument infoLog
-    GLMessage_DataType *arg_infoLog = glmsg.add_args();
-    arg_infoLog->set_isarray(false);
-    arg_infoLog->set_type(GLMessage::DataType::INT64);
-    arg_infoLog->add_int64value((uintptr_t)infoLog);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramInfoLog(program, bufSize, length, infoLog);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) infoLog,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetRenderbufferParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetRenderbufferParameteriv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetShaderiv(GLuint shader, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetShaderiv);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetShaderiv(shader, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetShaderInfoLog);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument infoLog
-    GLMessage_DataType *arg_infoLog = glmsg.add_args();
-    arg_infoLog->set_isarray(false);
-    arg_infoLog->set_type(GLMessage::DataType::INT64);
-    arg_infoLog->add_int64value((uintptr_t)infoLog);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetShaderInfoLog(shader, bufSize, length, infoLog);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) infoLog,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetShaderPrecisionFormat);
-
-    // copy argument shadertype
-    GLMessage_DataType *arg_shadertype = glmsg.add_args();
-    arg_shadertype->set_isarray(false);
-    arg_shadertype->set_type(GLMessage::DataType::ENUM);
-    arg_shadertype->add_intvalue((int)shadertype);
-
-    // copy argument precisiontype
-    GLMessage_DataType *arg_precisiontype = glmsg.add_args();
-    arg_precisiontype->set_isarray(false);
-    arg_precisiontype->set_type(GLMessage::DataType::ENUM);
-    arg_precisiontype->add_intvalue((int)precisiontype);
-
-    // copy argument range
-    GLMessage_DataType *arg_range = glmsg.add_args();
-    arg_range->set_isarray(false);
-    arg_range->set_type(GLMessage::DataType::INT64);
-    arg_range->add_int64value((uintptr_t)range);
-
-    // copy argument precision
-    GLMessage_DataType *arg_precision = glmsg.add_args();
-    arg_precision->set_isarray(false);
-    arg_precision->set_type(GLMessage::DataType::INT64);
-    arg_precision->add_int64value((uintptr_t)precision);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) range,
-        (void *) precision,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetShaderSource(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetShaderSource);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument source
-    GLMessage_DataType *arg_source = glmsg.add_args();
-    arg_source->set_isarray(false);
-    arg_source->set_type(GLMessage::DataType::INT64);
-    arg_source->add_int64value((uintptr_t)source);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetShaderSource(shader, bufSize, length, source);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) source,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-const GLubyte * GLTrace_glGetString(GLenum name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetString);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::ENUM);
-    arg_name->add_intvalue((int)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    const GLubyte * retValue = glContext->hooks->gl.glGetString(name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexParameterfv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexParameterfv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexParameteriv(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexParameteriv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetUniformfv(GLuint program, GLint location, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetUniformfv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetUniformfv(program, location, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetUniformiv(GLuint program, GLint location, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetUniformiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetUniformiv(program, location, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLint GLTrace_glGetUniformLocation(GLuint program, const GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetUniformLocation);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLint retValue = glContext->hooks->gl.glGetUniformLocation(program, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetVertexAttribfv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetVertexAttribfv(index, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetVertexAttribiv(GLuint index, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetVertexAttribiv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetVertexAttribiv(index, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetVertexAttribPointerv(GLuint index, GLenum pname, void ** pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetVertexAttribPointerv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetVertexAttribPointerv(index, pname, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glHint(GLenum target, GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glHint);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glHint(target, mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsBuffer(GLuint buffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsBuffer);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsBuffer(buffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsEnabled(GLenum cap) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsEnabled);
-
-    // copy argument cap
-    GLMessage_DataType *arg_cap = glmsg.add_args();
-    arg_cap->set_isarray(false);
-    arg_cap->set_type(GLMessage::DataType::ENUM);
-    arg_cap->add_intvalue((int)cap);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsEnabled(cap);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsFramebuffer(GLuint framebuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsFramebuffer);
-
-    // copy argument framebuffer
-    GLMessage_DataType *arg_framebuffer = glmsg.add_args();
-    arg_framebuffer->set_isarray(false);
-    arg_framebuffer->set_type(GLMessage::DataType::INT);
-    arg_framebuffer->add_intvalue(framebuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsFramebuffer(framebuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsProgram(GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsProgram);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsProgram(program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsRenderbuffer(GLuint renderbuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsRenderbuffer);
-
-    // copy argument renderbuffer
-    GLMessage_DataType *arg_renderbuffer = glmsg.add_args();
-    arg_renderbuffer->set_isarray(false);
-    arg_renderbuffer->set_type(GLMessage::DataType::INT);
-    arg_renderbuffer->add_intvalue(renderbuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsRenderbuffer(renderbuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsShader(GLuint shader) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsShader);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsShader(shader);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsTexture(GLuint texture) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsTexture);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsTexture(texture);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glLineWidth(GLfloat width) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLineWidth);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::FLOAT);
-    arg_width->add_floatvalue(width);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLineWidth(width);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLinkProgram(GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLinkProgram);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLinkProgram(program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPixelStorei(GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPixelStorei);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPixelStorei(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPolygonOffset(GLfloat factor, GLfloat units) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPolygonOffset);
-
-    // copy argument factor
-    GLMessage_DataType *arg_factor = glmsg.add_args();
-    arg_factor->set_isarray(false);
-    arg_factor->set_type(GLMessage::DataType::FLOAT);
-    arg_factor->add_floatvalue(factor);
-
-    // copy argument units
-    GLMessage_DataType *arg_units = glmsg.add_args();
-    arg_units->set_isarray(false);
-    arg_units->set_type(GLMessage::DataType::FLOAT);
-    arg_units->add_floatvalue(units);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPolygonOffset(factor, units);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glReadPixels);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glReadPixels(x, y, width, height, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glReleaseShaderCompiler(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glReleaseShaderCompiler);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glReleaseShaderCompiler();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorage);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorage(target, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSampleCoverage(GLfloat value, GLboolean invert) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSampleCoverage);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::FLOAT);
-    arg_value->add_floatvalue(value);
-
-    // copy argument invert
-    GLMessage_DataType *arg_invert = glmsg.add_args();
-    arg_invert->set_isarray(false);
-    arg_invert->set_type(GLMessage::DataType::BOOL);
-    arg_invert->add_boolvalue(invert);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSampleCoverage(value, invert);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glScissor);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glScissor(x, y, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glShaderBinary(GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glShaderBinary);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument shaders
-    GLMessage_DataType *arg_shaders = glmsg.add_args();
-    arg_shaders->set_isarray(false);
-    arg_shaders->set_type(GLMessage::DataType::INT64);
-    arg_shaders->add_int64value((uintptr_t)shaders);
-
-    // copy argument binaryformat
-    GLMessage_DataType *arg_binaryformat = glmsg.add_args();
-    arg_binaryformat->set_isarray(false);
-    arg_binaryformat->set_type(GLMessage::DataType::ENUM);
-    arg_binaryformat->add_intvalue((int)binaryformat);
-
-    // copy argument binary
-    GLMessage_DataType *arg_binary = glmsg.add_args();
-    arg_binary->set_isarray(false);
-    arg_binary->set_type(GLMessage::DataType::INT64);
-    arg_binary->add_int64value((uintptr_t)binary);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glShaderBinary(count, shaders, binaryformat, binary, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) shaders,
-        (void *) binary,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glShaderSource);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument string
-    GLMessage_DataType *arg_string = glmsg.add_args();
-    arg_string->set_isarray(false);
-    arg_string->set_type(GLMessage::DataType::INT64);
-    arg_string->add_int64value((uintptr_t)string);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glShaderSource(shader, count, string, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) string,
-        (void *) length,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStencilFunc(GLenum func, GLint ref, GLuint mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStencilFunc);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // copy argument ref
-    GLMessage_DataType *arg_ref = glmsg.add_args();
-    arg_ref->set_isarray(false);
-    arg_ref->set_type(GLMessage::DataType::INT);
-    arg_ref->add_intvalue(ref);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStencilFunc(func, ref, mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStencilFuncSeparate);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // copy argument ref
-    GLMessage_DataType *arg_ref = glmsg.add_args();
-    arg_ref->set_isarray(false);
-    arg_ref->set_type(GLMessage::DataType::INT);
-    arg_ref->add_intvalue(ref);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStencilFuncSeparate(face, func, ref, mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStencilMask(GLuint mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStencilMask);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStencilMask(mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStencilMaskSeparate(GLenum face, GLuint mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStencilMaskSeparate);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStencilMaskSeparate(face, mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStencilOp);
-
-    // copy argument fail
-    GLMessage_DataType *arg_fail = glmsg.add_args();
-    arg_fail->set_isarray(false);
-    arg_fail->set_type(GLMessage::DataType::ENUM);
-    arg_fail->add_intvalue((int)fail);
-
-    // copy argument zfail
-    GLMessage_DataType *arg_zfail = glmsg.add_args();
-    arg_zfail->set_isarray(false);
-    arg_zfail->set_type(GLMessage::DataType::ENUM);
-    arg_zfail->add_intvalue((int)zfail);
-
-    // copy argument zpass
-    GLMessage_DataType *arg_zpass = glmsg.add_args();
-    arg_zpass->set_isarray(false);
-    arg_zpass->set_type(GLMessage::DataType::ENUM);
-    arg_zpass->add_intvalue((int)zpass);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStencilOp(fail, zfail, zpass);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStencilOpSeparate);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument sfail
-    GLMessage_DataType *arg_sfail = glmsg.add_args();
-    arg_sfail->set_isarray(false);
-    arg_sfail->set_type(GLMessage::DataType::ENUM);
-    arg_sfail->add_intvalue((int)sfail);
-
-    // copy argument dpfail
-    GLMessage_DataType *arg_dpfail = glmsg.add_args();
-    arg_dpfail->set_isarray(false);
-    arg_dpfail->set_type(GLMessage::DataType::ENUM);
-    arg_dpfail->add_intvalue((int)dpfail);
-
-    // copy argument dppass
-    GLMessage_DataType *arg_dppass = glmsg.add_args();
-    arg_dppass->set_isarray(false);
-    arg_dppass->set_type(GLMessage::DataType::ENUM);
-    arg_dppass->add_intvalue((int)dppass);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStencilOpSeparate(face, sfail, dpfail, dppass);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexImage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::INT);
-    arg_internalformat->add_intvalue(internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterf(GLenum target, GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterf);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterf(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterfv(GLenum target, GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterfv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterfv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameteri(GLenum target, GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameteri);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameteri(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameteriv(GLenum target, GLenum pname, const GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameteriv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexSubImage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform1f(GLint location, GLfloat v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform1f);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform1f(location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform1fv(GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform1fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform1fv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform1i(GLint location, GLint v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform1i);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform1i(location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform1iv(GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform1iv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform1iv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform2f(GLint location, GLfloat v0, GLfloat v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform2f);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform2f(location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform2fv(GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform2fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform2fv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform2i(GLint location, GLint v0, GLint v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform2i);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform2i(location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform2iv(GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform2iv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform2iv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform3f);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::FLOAT);
-    arg_v2->add_floatvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform3f(location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform3fv(GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform3fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform3fv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform3i);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform3i(location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform3iv(GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform3iv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform3iv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform4f);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::FLOAT);
-    arg_v2->add_floatvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::FLOAT);
-    arg_v3->add_floatvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform4f(location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform4fv(GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform4fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform4fv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform4i);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::INT);
-    arg_v3->add_intvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform4i(location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform4iv(GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform4iv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform4iv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix2fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix2fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix3fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix3fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix4fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix4fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUseProgram(GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUseProgram);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUseProgram(program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glValidateProgram(GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glValidateProgram);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glValidateProgram(program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib1f(GLuint index, GLfloat x) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib1f);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib1f(index, x);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib1fv(GLuint index, const GLfloat * v) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib1fv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument v
-    GLMessage_DataType *arg_v = glmsg.add_args();
-    arg_v->set_isarray(false);
-    arg_v->set_type(GLMessage::DataType::INT64);
-    arg_v->add_int64value((uintptr_t)v);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib1fv(index, v);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) v,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib2f);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib2f(index, x, y);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib2fv(GLuint index, const GLfloat * v) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib2fv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument v
-    GLMessage_DataType *arg_v = glmsg.add_args();
-    arg_v->set_isarray(false);
-    arg_v->set_type(GLMessage::DataType::INT64);
-    arg_v->add_int64value((uintptr_t)v);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib2fv(index, v);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) v,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib3f);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::FLOAT);
-    arg_z->add_floatvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib3f(index, x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib3fv(GLuint index, const GLfloat * v) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib3fv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument v
-    GLMessage_DataType *arg_v = glmsg.add_args();
-    arg_v->set_isarray(false);
-    arg_v->set_type(GLMessage::DataType::INT64);
-    arg_v->add_int64value((uintptr_t)v);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib3fv(index, v);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) v,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib4f);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::FLOAT);
-    arg_z->add_floatvalue(z);
-
-    // copy argument w
-    GLMessage_DataType *arg_w = glmsg.add_args();
-    arg_w->set_isarray(false);
-    arg_w->set_type(GLMessage::DataType::FLOAT);
-    arg_w->add_floatvalue(w);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib4f(index, x, y, z, w);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttrib4fv(GLuint index, const GLfloat * v) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttrib4fv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument v
-    GLMessage_DataType *arg_v = glmsg.add_args();
-    arg_v->set_isarray(false);
-    arg_v->set_type(GLMessage::DataType::INT64);
-    arg_v->add_int64value((uintptr_t)v);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttrib4fv(index, v);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) v,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribPointer);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument normalized
-    GLMessage_DataType *arg_normalized = glmsg.add_args();
-    arg_normalized->set_isarray(false);
-    arg_normalized->set_type(GLMessage::DataType::BOOL);
-    arg_normalized->add_boolvalue(normalized);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribPointer(index, size, type, normalized, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glViewport);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glViewport(x, y, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glReadBuffer(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glReadBuffer);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glReadBuffer(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawRangeElements);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument start
-    GLMessage_DataType *arg_start = glmsg.add_args();
-    arg_start->set_isarray(false);
-    arg_start->set_type(GLMessage::DataType::INT);
-    arg_start->add_intvalue(start);
-
-    // copy argument end
-    GLMessage_DataType *arg_end = glmsg.add_args();
-    arg_end->set_isarray(false);
-    arg_end->set_type(GLMessage::DataType::INT);
-    arg_end->add_intvalue(end);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawRangeElements(mode, start, end, count, type, indices);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexImage3D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::INT);
-    arg_internalformat->add_intvalue(internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexSubImage3D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyTexSubImage3D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompressedTexImage3D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // copy argument imageSize
-    GLMessage_DataType *arg_imageSize = glmsg.add_args();
-    arg_imageSize->set_isarray(false);
-    arg_imageSize->set_type(GLMessage::DataType::INT);
-    arg_imageSize->add_intvalue(imageSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompressedTexSubImage3D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument imageSize
-    GLMessage_DataType *arg_imageSize = glmsg.add_args();
-    arg_imageSize->set_isarray(false);
-    arg_imageSize->set_type(GLMessage::DataType::INT);
-    arg_imageSize->add_intvalue(imageSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenQueries(GLsizei n, GLuint * ids) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenQueries);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenQueries(n, ids);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteQueries(GLsizei n, const GLuint * ids) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteQueries);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteQueries(n, ids);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsQuery(GLuint id) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsQuery);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsQuery(id);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glBeginQuery(GLenum target, GLuint id) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBeginQuery);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBeginQuery(target, id);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEndQuery(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEndQuery);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEndQuery(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryiv(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryiv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryiv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryObjectuiv);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryObjectuiv(id, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glUnmapBuffer(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUnmapBuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glUnmapBuffer(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetBufferPointerv(GLenum target, GLenum pname, void ** params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetBufferPointerv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetBufferPointerv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawBuffers(GLsizei n, const GLenum * bufs) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawBuffers);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument bufs
-    GLMessage_DataType *arg_bufs = glmsg.add_args();
-    arg_bufs->set_isarray(false);
-    arg_bufs->set_type(GLMessage::DataType::INT64);
-    arg_bufs->add_int64value((uintptr_t)bufs);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawBuffers(n, bufs);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) bufs,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix2x3fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix2x3fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix3x2fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix3x2fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix2x4fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix2x4fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix4x2fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix4x2fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix3x4fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix3x4fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix4x3fv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix4x3fv(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlitFramebuffer);
-
-    // copy argument srcX0
-    GLMessage_DataType *arg_srcX0 = glmsg.add_args();
-    arg_srcX0->set_isarray(false);
-    arg_srcX0->set_type(GLMessage::DataType::INT);
-    arg_srcX0->add_intvalue(srcX0);
-
-    // copy argument srcY0
-    GLMessage_DataType *arg_srcY0 = glmsg.add_args();
-    arg_srcY0->set_isarray(false);
-    arg_srcY0->set_type(GLMessage::DataType::INT);
-    arg_srcY0->add_intvalue(srcY0);
-
-    // copy argument srcX1
-    GLMessage_DataType *arg_srcX1 = glmsg.add_args();
-    arg_srcX1->set_isarray(false);
-    arg_srcX1->set_type(GLMessage::DataType::INT);
-    arg_srcX1->add_intvalue(srcX1);
-
-    // copy argument srcY1
-    GLMessage_DataType *arg_srcY1 = glmsg.add_args();
-    arg_srcY1->set_isarray(false);
-    arg_srcY1->set_type(GLMessage::DataType::INT);
-    arg_srcY1->add_intvalue(srcY1);
-
-    // copy argument dstX0
-    GLMessage_DataType *arg_dstX0 = glmsg.add_args();
-    arg_dstX0->set_isarray(false);
-    arg_dstX0->set_type(GLMessage::DataType::INT);
-    arg_dstX0->add_intvalue(dstX0);
-
-    // copy argument dstY0
-    GLMessage_DataType *arg_dstY0 = glmsg.add_args();
-    arg_dstY0->set_isarray(false);
-    arg_dstY0->set_type(GLMessage::DataType::INT);
-    arg_dstY0->add_intvalue(dstY0);
-
-    // copy argument dstX1
-    GLMessage_DataType *arg_dstX1 = glmsg.add_args();
-    arg_dstX1->set_isarray(false);
-    arg_dstX1->set_type(GLMessage::DataType::INT);
-    arg_dstX1->add_intvalue(dstX1);
-
-    // copy argument dstY1
-    GLMessage_DataType *arg_dstY1 = glmsg.add_args();
-    arg_dstY1->set_isarray(false);
-    arg_dstY1->set_type(GLMessage::DataType::INT);
-    arg_dstY1->add_intvalue(dstY1);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // copy argument filter
-    GLMessage_DataType *arg_filter = glmsg.add_args();
-    arg_filter->set_isarray(false);
-    arg_filter->set_type(GLMessage::DataType::ENUM);
-    arg_filter->add_intvalue((int)filter);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageMultisample);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTextureLayer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument layer
-    GLMessage_DataType *arg_layer = glmsg.add_args();
-    arg_layer->set_isarray(false);
-    arg_layer->set_type(GLMessage::DataType::INT);
-    arg_layer->add_intvalue(layer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTextureLayer(target, attachment, texture, level, layer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void * GLTrace_glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMapBufferRange);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument access
-    GLMessage_DataType *arg_access = glmsg.add_args();
-    arg_access->set_isarray(false);
-    arg_access->set_type(GLMessage::DataType::INT);
-    arg_access->add_intvalue(access);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    void * retValue = glContext->hooks->gl.glMapBufferRange(target, offset, length, access);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFlushMappedBufferRange);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFlushMappedBufferRange(target, offset, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindVertexArray(GLuint array) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindVertexArray);
-
-    // copy argument array
-    GLMessage_DataType *arg_array = glmsg.add_args();
-    arg_array->set_isarray(false);
-    arg_array->set_type(GLMessage::DataType::INT);
-    arg_array->add_intvalue(array);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindVertexArray(array);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteVertexArrays(GLsizei n, const GLuint * arrays) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteVertexArrays);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument arrays
-    GLMessage_DataType *arg_arrays = glmsg.add_args();
-    arg_arrays->set_isarray(false);
-    arg_arrays->set_type(GLMessage::DataType::INT64);
-    arg_arrays->add_int64value((uintptr_t)arrays);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteVertexArrays(n, arrays);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) arrays,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenVertexArrays(GLsizei n, GLuint * arrays) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenVertexArrays);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument arrays
-    GLMessage_DataType *arg_arrays = glmsg.add_args();
-    arg_arrays->set_isarray(false);
-    arg_arrays->set_type(GLMessage::DataType::INT64);
-    arg_arrays->add_int64value((uintptr_t)arrays);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenVertexArrays(n, arrays);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) arrays,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsVertexArray(GLuint array) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsVertexArray);
-
-    // copy argument array
-    GLMessage_DataType *arg_array = glmsg.add_args();
-    arg_array->set_isarray(false);
-    arg_array->set_type(GLMessage::DataType::INT);
-    arg_array->add_intvalue(array);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsVertexArray(array);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetIntegeri_v(GLenum target, GLuint index, GLint * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetIntegeri_v);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetIntegeri_v(target, index, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBeginTransformFeedback(GLenum primitiveMode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBeginTransformFeedback);
-
-    // copy argument primitiveMode
-    GLMessage_DataType *arg_primitiveMode = glmsg.add_args();
-    arg_primitiveMode->set_isarray(false);
-    arg_primitiveMode->set_type(GLMessage::DataType::ENUM);
-    arg_primitiveMode->add_intvalue((int)primitiveMode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBeginTransformFeedback(primitiveMode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEndTransformFeedback(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEndTransformFeedback);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEndTransformFeedback();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindBufferRange);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindBufferRange(target, index, buffer, offset, size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindBufferBase(GLenum target, GLuint index, GLuint buffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindBufferBase);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindBufferBase(target, index, buffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTransformFeedbackVaryings);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument varyings
-    GLMessage_DataType *arg_varyings = glmsg.add_args();
-    arg_varyings->set_isarray(false);
-    arg_varyings->set_type(GLMessage::DataType::INT64);
-    arg_varyings->add_int64value((uintptr_t)varyings);
-
-    // copy argument bufferMode
-    GLMessage_DataType *arg_bufferMode = glmsg.add_args();
-    arg_bufferMode->set_isarray(false);
-    arg_bufferMode->set_type(GLMessage::DataType::ENUM);
-    arg_bufferMode->add_intvalue((int)bufferMode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTransformFeedbackVaryings(program, count, varyings, bufferMode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) varyings,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTransformFeedbackVarying);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT64);
-    arg_size->add_int64value((uintptr_t)size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::INT64);
-    arg_type->add_int64value((uintptr_t)type);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) size,
-        (void *) type,
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribIPointer);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribIPointer(index, size, type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetVertexAttribIiv(GLuint index, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetVertexAttribIiv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetVertexAttribIiv(index, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetVertexAttribIuiv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetVertexAttribIuiv(index, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribI4i);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // copy argument w
-    GLMessage_DataType *arg_w = glmsg.add_args();
-    arg_w->set_isarray(false);
-    arg_w->set_type(GLMessage::DataType::INT);
-    arg_w->add_intvalue(w);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribI4i(index, x, y, z, w);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribI4ui);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // copy argument w
-    GLMessage_DataType *arg_w = glmsg.add_args();
-    arg_w->set_isarray(false);
-    arg_w->set_type(GLMessage::DataType::INT);
-    arg_w->add_intvalue(w);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribI4ui(index, x, y, z, w);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribI4iv(GLuint index, const GLint * v) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribI4iv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument v
-    GLMessage_DataType *arg_v = glmsg.add_args();
-    arg_v->set_isarray(false);
-    arg_v->set_type(GLMessage::DataType::INT64);
-    arg_v->add_int64value((uintptr_t)v);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribI4iv(index, v);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) v,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribI4uiv(GLuint index, const GLuint * v) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribI4uiv);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument v
-    GLMessage_DataType *arg_v = glmsg.add_args();
-    arg_v->set_isarray(false);
-    arg_v->set_type(GLMessage::DataType::INT64);
-    arg_v->add_int64value((uintptr_t)v);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribI4uiv(index, v);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) v,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetUniformuiv(GLuint program, GLint location, GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetUniformuiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetUniformuiv(program, location, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLint GLTrace_glGetFragDataLocation(GLuint program, const GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFragDataLocation);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLint retValue = glContext->hooks->gl.glGetFragDataLocation(program, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glUniform1ui(GLint location, GLuint v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform1ui);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform1ui(location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform2ui(GLint location, GLuint v0, GLuint v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform2ui);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform2ui(location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform3ui);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform3ui(location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform4ui);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::INT);
-    arg_v3->add_intvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform4ui(location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform1uiv(GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform1uiv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform1uiv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform2uiv(GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform2uiv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform2uiv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform3uiv(GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform3uiv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform3uiv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniform4uiv(GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniform4uiv);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniform4uiv(location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearBufferiv);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::ENUM);
-    arg_buffer->add_intvalue((int)buffer);
-
-    // copy argument drawbuffer
-    GLMessage_DataType *arg_drawbuffer = glmsg.add_args();
-    arg_drawbuffer->set_isarray(false);
-    arg_drawbuffer->set_type(GLMessage::DataType::INT);
-    arg_drawbuffer->add_intvalue(drawbuffer);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearBufferiv(buffer, drawbuffer, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearBufferuiv);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::ENUM);
-    arg_buffer->add_intvalue((int)buffer);
-
-    // copy argument drawbuffer
-    GLMessage_DataType *arg_drawbuffer = glmsg.add_args();
-    arg_drawbuffer->set_isarray(false);
-    arg_drawbuffer->set_type(GLMessage::DataType::INT);
-    arg_drawbuffer->add_intvalue(drawbuffer);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearBufferuiv(buffer, drawbuffer, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearBufferfv);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::ENUM);
-    arg_buffer->add_intvalue((int)buffer);
-
-    // copy argument drawbuffer
-    GLMessage_DataType *arg_drawbuffer = glmsg.add_args();
-    arg_drawbuffer->set_isarray(false);
-    arg_drawbuffer->set_type(GLMessage::DataType::INT);
-    arg_drawbuffer->add_intvalue(drawbuffer);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearBufferfv(buffer, drawbuffer, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearBufferfi);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::ENUM);
-    arg_buffer->add_intvalue((int)buffer);
-
-    // copy argument drawbuffer
-    GLMessage_DataType *arg_drawbuffer = glmsg.add_args();
-    arg_drawbuffer->set_isarray(false);
-    arg_drawbuffer->set_type(GLMessage::DataType::INT);
-    arg_drawbuffer->add_intvalue(drawbuffer);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::FLOAT);
-    arg_depth->add_floatvalue(depth);
-
-    // copy argument stencil
-    GLMessage_DataType *arg_stencil = glmsg.add_args();
-    arg_stencil->set_isarray(false);
-    arg_stencil->set_type(GLMessage::DataType::INT);
-    arg_stencil->add_intvalue(stencil);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearBufferfi(buffer, drawbuffer, depth, stencil);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-const GLubyte * GLTrace_glGetStringi(GLenum name, GLuint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetStringi);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::ENUM);
-    arg_name->add_intvalue((int)name);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    const GLubyte * retValue = glContext->hooks->gl.glGetStringi(name, index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyBufferSubData);
-
-    // copy argument readTarget
-    GLMessage_DataType *arg_readTarget = glmsg.add_args();
-    arg_readTarget->set_isarray(false);
-    arg_readTarget->set_type(GLMessage::DataType::ENUM);
-    arg_readTarget->add_intvalue((int)readTarget);
-
-    // copy argument writeTarget
-    GLMessage_DataType *arg_writeTarget = glmsg.add_args();
-    arg_writeTarget->set_isarray(false);
-    arg_writeTarget->set_type(GLMessage::DataType::ENUM);
-    arg_writeTarget->add_intvalue((int)writeTarget);
-
-    // copy argument readOffset
-    GLMessage_DataType *arg_readOffset = glmsg.add_args();
-    arg_readOffset->set_isarray(false);
-    arg_readOffset->set_type(GLMessage::DataType::INT);
-    arg_readOffset->add_intvalue(readOffset);
-
-    // copy argument writeOffset
-    GLMessage_DataType *arg_writeOffset = glmsg.add_args();
-    arg_writeOffset->set_isarray(false);
-    arg_writeOffset->set_type(GLMessage::DataType::INT);
-    arg_writeOffset->add_intvalue(writeOffset);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetUniformIndices);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument uniformCount
-    GLMessage_DataType *arg_uniformCount = glmsg.add_args();
-    arg_uniformCount->set_isarray(false);
-    arg_uniformCount->set_type(GLMessage::DataType::INT);
-    arg_uniformCount->add_intvalue(uniformCount);
-
-    // copy argument uniformNames
-    GLMessage_DataType *arg_uniformNames = glmsg.add_args();
-    arg_uniformNames->set_isarray(false);
-    arg_uniformNames->set_type(GLMessage::DataType::INT64);
-    arg_uniformNames->add_int64value((uintptr_t)uniformNames);
-
-    // copy argument uniformIndices
-    GLMessage_DataType *arg_uniformIndices = glmsg.add_args();
-    arg_uniformIndices->set_isarray(false);
-    arg_uniformIndices->set_type(GLMessage::DataType::INT64);
-    arg_uniformIndices->add_int64value((uintptr_t)uniformIndices);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetUniformIndices(program, uniformCount, uniformNames, uniformIndices);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) uniformNames,
-        (void *) uniformIndices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetActiveUniformsiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument uniformCount
-    GLMessage_DataType *arg_uniformCount = glmsg.add_args();
-    arg_uniformCount->set_isarray(false);
-    arg_uniformCount->set_type(GLMessage::DataType::INT);
-    arg_uniformCount->add_intvalue(uniformCount);
-
-    // copy argument uniformIndices
-    GLMessage_DataType *arg_uniformIndices = glmsg.add_args();
-    arg_uniformIndices->set_isarray(false);
-    arg_uniformIndices->set_type(GLMessage::DataType::INT64);
-    arg_uniformIndices->add_int64value((uintptr_t)uniformIndices);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) uniformIndices,
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLuint GLTrace_glGetUniformBlockIndex(GLuint program, const GLchar * uniformBlockName) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetUniformBlockIndex);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument uniformBlockName
-    GLMessage_DataType *arg_uniformBlockName = glmsg.add_args();
-    arg_uniformBlockName->set_isarray(false);
-    arg_uniformBlockName->set_type(GLMessage::DataType::INT64);
-    arg_uniformBlockName->add_int64value((uintptr_t)uniformBlockName);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glGetUniformBlockIndex(program, uniformBlockName);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) uniformBlockName,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetActiveUniformBlockiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument uniformBlockIndex
-    GLMessage_DataType *arg_uniformBlockIndex = glmsg.add_args();
-    arg_uniformBlockIndex->set_isarray(false);
-    arg_uniformBlockIndex->set_type(GLMessage::DataType::INT);
-    arg_uniformBlockIndex->add_intvalue(uniformBlockIndex);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetActiveUniformBlockiv(program, uniformBlockIndex, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetActiveUniformBlockName);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument uniformBlockIndex
-    GLMessage_DataType *arg_uniformBlockIndex = glmsg.add_args();
-    arg_uniformBlockIndex->set_isarray(false);
-    arg_uniformBlockIndex->set_type(GLMessage::DataType::INT);
-    arg_uniformBlockIndex->add_intvalue(uniformBlockIndex);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument uniformBlockName
-    GLMessage_DataType *arg_uniformBlockName = glmsg.add_args();
-    arg_uniformBlockName->set_isarray(false);
-    arg_uniformBlockName->set_type(GLMessage::DataType::INT64);
-    arg_uniformBlockName->add_int64value((uintptr_t)uniformBlockName);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) uniformBlockName,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformBlockBinding);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument uniformBlockIndex
-    GLMessage_DataType *arg_uniformBlockIndex = glmsg.add_args();
-    arg_uniformBlockIndex->set_isarray(false);
-    arg_uniformBlockIndex->set_type(GLMessage::DataType::INT);
-    arg_uniformBlockIndex->add_intvalue(uniformBlockIndex);
-
-    // copy argument uniformBlockBinding
-    GLMessage_DataType *arg_uniformBlockBinding = glmsg.add_args();
-    arg_uniformBlockBinding->set_isarray(false);
-    arg_uniformBlockBinding->set_type(GLMessage::DataType::INT);
-    arg_uniformBlockBinding->add_intvalue(uniformBlockBinding);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawArraysInstanced);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument first
-    GLMessage_DataType *arg_first = glmsg.add_args();
-    arg_first->set_isarray(false);
-    arg_first->set_type(GLMessage::DataType::INT);
-    arg_first->add_intvalue(first);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument instancecount
-    GLMessage_DataType *arg_instancecount = glmsg.add_args();
-    arg_instancecount->set_isarray(false);
-    arg_instancecount->set_type(GLMessage::DataType::INT);
-    arg_instancecount->add_intvalue(instancecount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawArraysInstanced(mode, first, count, instancecount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawElementsInstanced);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // copy argument instancecount
-    GLMessage_DataType *arg_instancecount = glmsg.add_args();
-    arg_instancecount->set_isarray(false);
-    arg_instancecount->set_type(GLMessage::DataType::INT);
-    arg_instancecount->add_intvalue(instancecount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawElementsInstanced(mode, count, type, indices, instancecount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLsync GLTrace_glFenceSync(GLenum condition, GLbitfield flags) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFenceSync);
-
-    // copy argument condition
-    GLMessage_DataType *arg_condition = glmsg.add_args();
-    arg_condition->set_isarray(false);
-    arg_condition->set_type(GLMessage::DataType::ENUM);
-    arg_condition->add_intvalue((int)condition);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLsync retValue = glContext->hooks->gl.glFenceSync(condition, flags);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsSync(GLsync sync) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsSync);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsSync(sync);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glDeleteSync(GLsync sync) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteSync);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteSync(sync);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLenum GLTrace_glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClientWaitSync);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // copy argument timeout
-    GLMessage_DataType *arg_timeout = glmsg.add_args();
-    arg_timeout->set_isarray(false);
-    arg_timeout->set_type(GLMessage::DataType::INT64);
-    arg_timeout->add_int64value(timeout);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLenum retValue = glContext->hooks->gl.glClientWaitSync(sync, flags, timeout);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::ENUM);
-    rt->add_intvalue((int)retValue);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glWaitSync);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // copy argument timeout
-    GLMessage_DataType *arg_timeout = glmsg.add_args();
-    arg_timeout->set_isarray(false);
-    arg_timeout->set_type(GLMessage::DataType::INT64);
-    arg_timeout->add_int64value(timeout);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glWaitSync(sync, flags, timeout);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetInteger64v(GLenum pname, GLint64 * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetInteger64v);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetInteger64v(pname, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetSynciv);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument values
-    GLMessage_DataType *arg_values = glmsg.add_args();
-    arg_values->set_isarray(false);
-    arg_values->set_type(GLMessage::DataType::INT64);
-    arg_values->add_int64value((uintptr_t)values);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetSynciv(sync, pname, bufSize, length, values);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-        (void *) length,
-        (void *) values,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetInteger64i_v(GLenum target, GLuint index, GLint64 * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetInteger64i_v);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetInteger64i_v(target, index, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetBufferParameteri64v);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetBufferParameteri64v(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenSamplers(GLsizei count, GLuint * samplers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenSamplers);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument samplers
-    GLMessage_DataType *arg_samplers = glmsg.add_args();
-    arg_samplers->set_isarray(false);
-    arg_samplers->set_type(GLMessage::DataType::INT64);
-    arg_samplers->add_int64value((uintptr_t)samplers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenSamplers(count, samplers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) samplers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteSamplers(GLsizei count, const GLuint * samplers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteSamplers);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument samplers
-    GLMessage_DataType *arg_samplers = glmsg.add_args();
-    arg_samplers->set_isarray(false);
-    arg_samplers->set_type(GLMessage::DataType::INT64);
-    arg_samplers->add_int64value((uintptr_t)samplers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteSamplers(count, samplers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) samplers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsSampler(GLuint sampler) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsSampler);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsSampler(sampler);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glBindSampler(GLuint unit, GLuint sampler) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindSampler);
-
-    // copy argument unit
-    GLMessage_DataType *arg_unit = glmsg.add_args();
-    arg_unit->set_isarray(false);
-    arg_unit->set_type(GLMessage::DataType::INT);
-    arg_unit->add_intvalue(unit);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindSampler(unit, sampler);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSamplerParameteri);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSamplerParameteri(sampler, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSamplerParameteriv);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSamplerParameteriv(sampler, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSamplerParameterf);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSamplerParameterf(sampler, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSamplerParameterfv);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSamplerParameterfv(sampler, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetSamplerParameteriv);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetSamplerParameteriv(sampler, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetSamplerParameterfv);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetSamplerParameterfv(sampler, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribDivisor(GLuint index, GLuint divisor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribDivisor);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument divisor
-    GLMessage_DataType *arg_divisor = glmsg.add_args();
-    arg_divisor->set_isarray(false);
-    arg_divisor->set_type(GLMessage::DataType::INT);
-    arg_divisor->add_intvalue(divisor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribDivisor(index, divisor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindTransformFeedback(GLenum target, GLuint id) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindTransformFeedback);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindTransformFeedback(target, id);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteTransformFeedbacks(GLsizei n, const GLuint * ids) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteTransformFeedbacks);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteTransformFeedbacks(n, ids);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenTransformFeedbacks(GLsizei n, GLuint * ids) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenTransformFeedbacks);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenTransformFeedbacks(n, ids);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsTransformFeedback(GLuint id) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsTransformFeedback);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsTransformFeedback(id);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glPauseTransformFeedback(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPauseTransformFeedback);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPauseTransformFeedback();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glResumeTransformFeedback(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glResumeTransformFeedback);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glResumeTransformFeedback();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramBinary);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument binaryFormat
-    GLMessage_DataType *arg_binaryFormat = glmsg.add_args();
-    arg_binaryFormat->set_isarray(false);
-    arg_binaryFormat->set_type(GLMessage::DataType::INT64);
-    arg_binaryFormat->add_int64value((uintptr_t)binaryFormat);
-
-    // copy argument binary
-    GLMessage_DataType *arg_binary = glmsg.add_args();
-    arg_binary->set_isarray(false);
-    arg_binary->set_type(GLMessage::DataType::INT64);
-    arg_binary->add_int64value((uintptr_t)binary);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramBinary(program, bufSize, length, binaryFormat, binary);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) binaryFormat,
-        (void *) binary,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramBinary(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramBinary);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument binaryFormat
-    GLMessage_DataType *arg_binaryFormat = glmsg.add_args();
-    arg_binaryFormat->set_isarray(false);
-    arg_binaryFormat->set_type(GLMessage::DataType::ENUM);
-    arg_binaryFormat->add_intvalue((int)binaryFormat);
-
-    // copy argument binary
-    GLMessage_DataType *arg_binary = glmsg.add_args();
-    arg_binary->set_isarray(false);
-    arg_binary->set_type(GLMessage::DataType::INT64);
-    arg_binary->add_int64value((uintptr_t)binary);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramBinary(program, binaryFormat, binary, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) binary,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramParameteri(GLuint program, GLenum pname, GLint value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramParameteri);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramParameteri(program, pname, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum * attachments) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glInvalidateFramebuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument numAttachments
-    GLMessage_DataType *arg_numAttachments = glmsg.add_args();
-    arg_numAttachments->set_isarray(false);
-    arg_numAttachments->set_type(GLMessage::DataType::INT);
-    arg_numAttachments->add_intvalue(numAttachments);
-
-    // copy argument attachments
-    GLMessage_DataType *arg_attachments = glmsg.add_args();
-    arg_attachments->set_isarray(false);
-    arg_attachments->set_type(GLMessage::DataType::INT64);
-    arg_attachments->add_int64value((uintptr_t)attachments);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glInvalidateFramebuffer(target, numAttachments, attachments);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) attachments,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glInvalidateSubFramebuffer);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument numAttachments
-    GLMessage_DataType *arg_numAttachments = glmsg.add_args();
-    arg_numAttachments->set_isarray(false);
-    arg_numAttachments->set_type(GLMessage::DataType::INT);
-    arg_numAttachments->add_intvalue(numAttachments);
-
-    // copy argument attachments
-    GLMessage_DataType *arg_attachments = glmsg.add_args();
-    arg_attachments->set_isarray(false);
-    arg_attachments->set_type(GLMessage::DataType::INT64);
-    arg_attachments->add_int64value((uintptr_t)attachments);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glInvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) attachments,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage2D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage2D(target, levels, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage3D);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage3D(target, levels, internalformat, width, height, depth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetInternalformativ);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetInternalformativ(target, internalformat, pname, bufSize, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDispatchCompute);
-
-    // copy argument num_groups_x
-    GLMessage_DataType *arg_num_groups_x = glmsg.add_args();
-    arg_num_groups_x->set_isarray(false);
-    arg_num_groups_x->set_type(GLMessage::DataType::INT);
-    arg_num_groups_x->add_intvalue(num_groups_x);
-
-    // copy argument num_groups_y
-    GLMessage_DataType *arg_num_groups_y = glmsg.add_args();
-    arg_num_groups_y->set_isarray(false);
-    arg_num_groups_y->set_type(GLMessage::DataType::INT);
-    arg_num_groups_y->add_intvalue(num_groups_y);
-
-    // copy argument num_groups_z
-    GLMessage_DataType *arg_num_groups_z = glmsg.add_args();
-    arg_num_groups_z->set_isarray(false);
-    arg_num_groups_z->set_type(GLMessage::DataType::INT);
-    arg_num_groups_z->add_intvalue(num_groups_z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDispatchCompute(num_groups_x, num_groups_y, num_groups_z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDispatchComputeIndirect(GLintptr indirect) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDispatchComputeIndirect);
-
-    // copy argument indirect
-    GLMessage_DataType *arg_indirect = glmsg.add_args();
-    arg_indirect->set_isarray(false);
-    arg_indirect->set_type(GLMessage::DataType::INT);
-    arg_indirect->add_intvalue(indirect);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDispatchComputeIndirect(indirect);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawArraysIndirect(GLenum mode, const void * indirect) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawArraysIndirect);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument indirect
-    GLMessage_DataType *arg_indirect = glmsg.add_args();
-    arg_indirect->set_isarray(false);
-    arg_indirect->set_type(GLMessage::DataType::INT64);
-    arg_indirect->add_int64value((uintptr_t)indirect);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawArraysIndirect(mode, indirect);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indirect,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawElementsIndirect(GLenum mode, GLenum type, const void * indirect) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawElementsIndirect);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indirect
-    GLMessage_DataType *arg_indirect = glmsg.add_args();
-    arg_indirect->set_isarray(false);
-    arg_indirect->set_type(GLMessage::DataType::INT64);
-    arg_indirect->add_int64value((uintptr_t)indirect);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawElementsIndirect(mode, type, indirect);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indirect,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferParameteri(GLenum target, GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferParameteri);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferParameteri(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFramebufferParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFramebufferParameteriv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramInterfaceiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument programInterface
-    GLMessage_DataType *arg_programInterface = glmsg.add_args();
-    arg_programInterface->set_isarray(false);
-    arg_programInterface->set_type(GLMessage::DataType::ENUM);
-    arg_programInterface->add_intvalue((int)programInterface);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramInterfaceiv(program, programInterface, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLuint GLTrace_glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramResourceIndex);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument programInterface
-    GLMessage_DataType *arg_programInterface = glmsg.add_args();
-    arg_programInterface->set_isarray(false);
-    arg_programInterface->set_type(GLMessage::DataType::ENUM);
-    arg_programInterface->add_intvalue((int)programInterface);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glGetProgramResourceIndex(program, programInterface, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramResourceName);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument programInterface
-    GLMessage_DataType *arg_programInterface = glmsg.add_args();
-    arg_programInterface->set_isarray(false);
-    arg_programInterface->set_type(GLMessage::DataType::ENUM);
-    arg_programInterface->add_intvalue((int)programInterface);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramResourceName(program, programInterface, index, bufSize, length, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramResourceiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument programInterface
-    GLMessage_DataType *arg_programInterface = glmsg.add_args();
-    arg_programInterface->set_isarray(false);
-    arg_programInterface->set_type(GLMessage::DataType::ENUM);
-    arg_programInterface->add_intvalue((int)programInterface);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument propCount
-    GLMessage_DataType *arg_propCount = glmsg.add_args();
-    arg_propCount->set_isarray(false);
-    arg_propCount->set_type(GLMessage::DataType::INT);
-    arg_propCount->add_intvalue(propCount);
-
-    // copy argument props
-    GLMessage_DataType *arg_props = glmsg.add_args();
-    arg_props->set_isarray(false);
-    arg_props->set_type(GLMessage::DataType::INT64);
-    arg_props->add_int64value((uintptr_t)props);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramResourceiv(program, programInterface, index, propCount, props, bufSize, length, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) props,
-        (void *) length,
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLint GLTrace_glGetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar * name) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramResourceLocation);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument programInterface
-    GLMessage_DataType *arg_programInterface = glmsg.add_args();
-    arg_programInterface->set_isarray(false);
-    arg_programInterface->set_type(GLMessage::DataType::ENUM);
-    arg_programInterface->add_intvalue((int)programInterface);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT64);
-    arg_name->add_int64value((uintptr_t)name);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLint retValue = glContext->hooks->gl.glGetProgramResourceLocation(program, programInterface, name);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) name,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUseProgramStages);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument stages
-    GLMessage_DataType *arg_stages = glmsg.add_args();
-    arg_stages->set_isarray(false);
-    arg_stages->set_type(GLMessage::DataType::INT);
-    arg_stages->add_intvalue(stages);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUseProgramStages(pipeline, stages, program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glActiveShaderProgram(GLuint pipeline, GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glActiveShaderProgram);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glActiveShaderProgram(pipeline, program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLuint GLTrace_glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const* strings) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCreateShaderProgramv);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument strings
-    GLMessage_DataType *arg_strings = glmsg.add_args();
-    arg_strings->set_isarray(false);
-    arg_strings->set_type(GLMessage::DataType::INT64);
-    arg_strings->add_int64value((uintptr_t)strings);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glCreateShaderProgramv(type, count, strings);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) strings,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glBindProgramPipeline(GLuint pipeline) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindProgramPipeline);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindProgramPipeline(pipeline);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteProgramPipelines(GLsizei n, const GLuint * pipelines) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteProgramPipelines);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument pipelines
-    GLMessage_DataType *arg_pipelines = glmsg.add_args();
-    arg_pipelines->set_isarray(false);
-    arg_pipelines->set_type(GLMessage::DataType::INT64);
-    arg_pipelines->add_int64value((uintptr_t)pipelines);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteProgramPipelines(n, pipelines);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pipelines,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenProgramPipelines(GLsizei n, GLuint * pipelines) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenProgramPipelines);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument pipelines
-    GLMessage_DataType *arg_pipelines = glmsg.add_args();
-    arg_pipelines->set_isarray(false);
-    arg_pipelines->set_type(GLMessage::DataType::INT64);
-    arg_pipelines->add_int64value((uintptr_t)pipelines);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenProgramPipelines(n, pipelines);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pipelines,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsProgramPipeline(GLuint pipeline) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsProgramPipeline);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsProgramPipeline(pipeline);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramPipelineiv);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramPipelineiv(pipeline, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1i(GLuint program, GLint location, GLint v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1i);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1i(program, location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2i);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2i(program, location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3i);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3i(program, location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4i);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::INT);
-    arg_v3->add_intvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4i(program, location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1ui(GLuint program, GLint location, GLuint v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1ui);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1ui(program, location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2ui);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2ui(program, location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3ui);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3ui(program, location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4ui);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::INT);
-    arg_v3->add_intvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4ui(program, location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1f(GLuint program, GLint location, GLfloat v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1f);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1f(program, location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2f);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2f(program, location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3f);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::FLOAT);
-    arg_v2->add_floatvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3f(program, location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4f);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::FLOAT);
-    arg_v2->add_floatvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::FLOAT);
-    arg_v3->add_floatvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4f(program, location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1iv(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1iv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1iv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2iv(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2iv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2iv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3iv(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3iv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3iv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4iv(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4iv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4iv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1uiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1uiv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2uiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2uiv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3uiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3uiv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4uiv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4uiv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1fv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2fv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3fv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4fv(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix2fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix2fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix3fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix3fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix4fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix4fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix2x3fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix2x3fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix3x2fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix3x2fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix2x4fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix2x4fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix4x2fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix4x2fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix3x4fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix3x4fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix4x3fv);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix4x3fv(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glValidateProgramPipeline(GLuint pipeline) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glValidateProgramPipeline);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glValidateProgramPipeline(pipeline);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramPipelineInfoLog);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument infoLog
-    GLMessage_DataType *arg_infoLog = glmsg.add_args();
-    arg_infoLog->set_isarray(false);
-    arg_infoLog->set_type(GLMessage::DataType::INT64);
-    arg_infoLog->add_int64value((uintptr_t)infoLog);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramPipelineInfoLog(pipeline, bufSize, length, infoLog);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) infoLog,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindImageTexture);
-
-    // copy argument unit
-    GLMessage_DataType *arg_unit = glmsg.add_args();
-    arg_unit->set_isarray(false);
-    arg_unit->set_type(GLMessage::DataType::INT);
-    arg_unit->add_intvalue(unit);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument layered
-    GLMessage_DataType *arg_layered = glmsg.add_args();
-    arg_layered->set_isarray(false);
-    arg_layered->set_type(GLMessage::DataType::BOOL);
-    arg_layered->add_boolvalue(layered);
-
-    // copy argument layer
-    GLMessage_DataType *arg_layer = glmsg.add_args();
-    arg_layer->set_isarray(false);
-    arg_layer->set_type(GLMessage::DataType::INT);
-    arg_layer->add_intvalue(layer);
-
-    // copy argument access
-    GLMessage_DataType *arg_access = glmsg.add_args();
-    arg_access->set_isarray(false);
-    arg_access->set_type(GLMessage::DataType::ENUM);
-    arg_access->add_intvalue((int)access);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindImageTexture(unit, texture, level, layered, layer, access, format);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetBooleani_v(GLenum target, GLuint index, GLboolean * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetBooleani_v);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetBooleani_v(target, index, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMemoryBarrier(GLbitfield barriers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMemoryBarrier);
-
-    // copy argument barriers
-    GLMessage_DataType *arg_barriers = glmsg.add_args();
-    arg_barriers->set_isarray(false);
-    arg_barriers->set_type(GLMessage::DataType::INT);
-    arg_barriers->add_intvalue(barriers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMemoryBarrier(barriers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMemoryBarrierByRegion(GLbitfield barriers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMemoryBarrierByRegion);
-
-    // copy argument barriers
-    GLMessage_DataType *arg_barriers = glmsg.add_args();
-    arg_barriers->set_isarray(false);
-    arg_barriers->set_type(GLMessage::DataType::INT);
-    arg_barriers->add_intvalue(barriers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMemoryBarrierByRegion(barriers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage2DMultisample);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument fixedsamplelocations
-    GLMessage_DataType *arg_fixedsamplelocations = glmsg.add_args();
-    arg_fixedsamplelocations->set_isarray(false);
-    arg_fixedsamplelocations->set_type(GLMessage::DataType::BOOL);
-    arg_fixedsamplelocations->add_boolvalue(fixedsamplelocations);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetMultisamplefv(GLenum pname, GLuint index, GLfloat * val) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetMultisamplefv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument val
-    GLMessage_DataType *arg_val = glmsg.add_args();
-    arg_val->set_isarray(false);
-    arg_val->set_type(GLMessage::DataType::INT64);
-    arg_val->add_int64value((uintptr_t)val);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetMultisamplefv(pname, index, val);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) val,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSampleMaski(GLuint maskNumber, GLbitfield mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSampleMaski);
-
-    // copy argument maskNumber
-    GLMessage_DataType *arg_maskNumber = glmsg.add_args();
-    arg_maskNumber->set_isarray(false);
-    arg_maskNumber->set_type(GLMessage::DataType::INT);
-    arg_maskNumber->add_intvalue(maskNumber);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSampleMaski(maskNumber, mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexLevelParameteriv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexLevelParameteriv(target, level, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexLevelParameterfv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexLevelParameterfv(target, level, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindVertexBuffer);
-
-    // copy argument bindingindex
-    GLMessage_DataType *arg_bindingindex = glmsg.add_args();
-    arg_bindingindex->set_isarray(false);
-    arg_bindingindex->set_type(GLMessage::DataType::INT);
-    arg_bindingindex->add_intvalue(bindingindex);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindVertexBuffer(bindingindex, buffer, offset, stride);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribFormat);
-
-    // copy argument attribindex
-    GLMessage_DataType *arg_attribindex = glmsg.add_args();
-    arg_attribindex->set_isarray(false);
-    arg_attribindex->set_type(GLMessage::DataType::INT);
-    arg_attribindex->add_intvalue(attribindex);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument normalized
-    GLMessage_DataType *arg_normalized = glmsg.add_args();
-    arg_normalized->set_isarray(false);
-    arg_normalized->set_type(GLMessage::DataType::BOOL);
-    arg_normalized->add_boolvalue(normalized);
-
-    // copy argument relativeoffset
-    GLMessage_DataType *arg_relativeoffset = glmsg.add_args();
-    arg_relativeoffset->set_isarray(false);
-    arg_relativeoffset->set_type(GLMessage::DataType::INT);
-    arg_relativeoffset->add_intvalue(relativeoffset);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribFormat(attribindex, size, type, normalized, relativeoffset);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribIFormat);
-
-    // copy argument attribindex
-    GLMessage_DataType *arg_attribindex = glmsg.add_args();
-    arg_attribindex->set_isarray(false);
-    arg_attribindex->set_type(GLMessage::DataType::INT);
-    arg_attribindex->add_intvalue(attribindex);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument relativeoffset
-    GLMessage_DataType *arg_relativeoffset = glmsg.add_args();
-    arg_relativeoffset->set_isarray(false);
-    arg_relativeoffset->set_type(GLMessage::DataType::INT);
-    arg_relativeoffset->add_intvalue(relativeoffset);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribIFormat(attribindex, size, type, relativeoffset);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribBinding(GLuint attribindex, GLuint bindingindex) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribBinding);
-
-    // copy argument attribindex
-    GLMessage_DataType *arg_attribindex = glmsg.add_args();
-    arg_attribindex->set_isarray(false);
-    arg_attribindex->set_type(GLMessage::DataType::INT);
-    arg_attribindex->add_intvalue(attribindex);
-
-    // copy argument bindingindex
-    GLMessage_DataType *arg_bindingindex = glmsg.add_args();
-    arg_bindingindex->set_isarray(false);
-    arg_bindingindex->set_type(GLMessage::DataType::INT);
-    arg_bindingindex->add_intvalue(bindingindex);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribBinding(attribindex, bindingindex);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexBindingDivisor(GLuint bindingindex, GLuint divisor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexBindingDivisor);
-
-    // copy argument bindingindex
-    GLMessage_DataType *arg_bindingindex = glmsg.add_args();
-    arg_bindingindex->set_isarray(false);
-    arg_bindingindex->set_type(GLMessage::DataType::INT);
-    arg_bindingindex->add_intvalue(bindingindex);
-
-    // copy argument divisor
-    GLMessage_DataType *arg_divisor = glmsg.add_args();
-    arg_divisor->set_isarray(false);
-    arg_divisor->set_type(GLMessage::DataType::INT);
-    arg_divisor->add_intvalue(divisor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexBindingDivisor(bindingindex, divisor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-
-// Definitions for GL2Ext APIs
-
-void GLTrace_glBlendBarrierKHR(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendBarrierKHR);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendBarrierKHR();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDebugMessageControlKHR(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDebugMessageControlKHR);
-
-    // copy argument source
-    GLMessage_DataType *arg_source = glmsg.add_args();
-    arg_source->set_isarray(false);
-    arg_source->set_type(GLMessage::DataType::ENUM);
-    arg_source->add_intvalue((int)source);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument severity
-    GLMessage_DataType *arg_severity = glmsg.add_args();
-    arg_severity->set_isarray(false);
-    arg_severity->set_type(GLMessage::DataType::ENUM);
-    arg_severity->add_intvalue((int)severity);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // copy argument enabled
-    GLMessage_DataType *arg_enabled = glmsg.add_args();
-    arg_enabled->set_isarray(false);
-    arg_enabled->set_type(GLMessage::DataType::BOOL);
-    arg_enabled->add_boolvalue(enabled);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDebugMessageControlKHR(source, type, severity, count, ids, enabled);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDebugMessageInsertKHR(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDebugMessageInsertKHR);
-
-    // copy argument source
-    GLMessage_DataType *arg_source = glmsg.add_args();
-    arg_source->set_isarray(false);
-    arg_source->set_type(GLMessage::DataType::ENUM);
-    arg_source->add_intvalue((int)source);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument severity
-    GLMessage_DataType *arg_severity = glmsg.add_args();
-    arg_severity->set_isarray(false);
-    arg_severity->set_type(GLMessage::DataType::ENUM);
-    arg_severity->add_intvalue((int)severity);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument buf
-    GLMessage_DataType *arg_buf = glmsg.add_args();
-    arg_buf->set_isarray(false);
-    arg_buf->set_type(GLMessage::DataType::INT64);
-    arg_buf->add_int64value((uintptr_t)buf);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDebugMessageInsertKHR(source, type, id, severity, length, buf);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) buf,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void * userParam) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDebugMessageCallbackKHR);
-
-    // copy argument callback
-    GLMessage_DataType *arg_callback = glmsg.add_args();
-    arg_callback->set_isarray(false);
-    arg_callback->set_type(GLMessage::DataType::INT64);
-    arg_callback->add_int64value((uintptr_t)callback);
-
-    // copy argument userParam
-    GLMessage_DataType *arg_userParam = glmsg.add_args();
-    arg_userParam->set_isarray(false);
-    arg_userParam->set_type(GLMessage::DataType::INT64);
-    arg_userParam->add_int64value((uintptr_t)userParam);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDebugMessageCallbackKHR(callback, userParam);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) callback,
-        (void *) userParam,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLuint GLTrace_glGetDebugMessageLogKHR(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetDebugMessageLogKHR);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument sources
-    GLMessage_DataType *arg_sources = glmsg.add_args();
-    arg_sources->set_isarray(false);
-    arg_sources->set_type(GLMessage::DataType::INT64);
-    arg_sources->add_int64value((uintptr_t)sources);
-
-    // copy argument types
-    GLMessage_DataType *arg_types = glmsg.add_args();
-    arg_types->set_isarray(false);
-    arg_types->set_type(GLMessage::DataType::INT64);
-    arg_types->add_int64value((uintptr_t)types);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // copy argument severities
-    GLMessage_DataType *arg_severities = glmsg.add_args();
-    arg_severities->set_isarray(false);
-    arg_severities->set_type(GLMessage::DataType::INT64);
-    arg_severities->add_int64value((uintptr_t)severities);
-
-    // copy argument lengths
-    GLMessage_DataType *arg_lengths = glmsg.add_args();
-    arg_lengths->set_isarray(false);
-    arg_lengths->set_type(GLMessage::DataType::INT64);
-    arg_lengths->add_int64value((uintptr_t)lengths);
-
-    // copy argument messageLog
-    GLMessage_DataType *arg_messageLog = glmsg.add_args();
-    arg_messageLog->set_isarray(false);
-    arg_messageLog->set_type(GLMessage::DataType::INT64);
-    arg_messageLog->add_int64value((uintptr_t)messageLog);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glGetDebugMessageLogKHR(count, bufSize, sources, types, ids, severities, lengths, messageLog);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) sources,
-        (void *) types,
-        (void *) ids,
-        (void *) severities,
-        (void *) lengths,
-        (void *) messageLog,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glPushDebugGroupKHR(GLenum source, GLuint id, GLsizei length, const GLchar * message) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPushDebugGroupKHR);
-
-    // copy argument source
-    GLMessage_DataType *arg_source = glmsg.add_args();
-    arg_source->set_isarray(false);
-    arg_source->set_type(GLMessage::DataType::ENUM);
-    arg_source->add_intvalue((int)source);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument message
-    GLMessage_DataType *arg_message = glmsg.add_args();
-    arg_message->set_isarray(false);
-    arg_message->set_type(GLMessage::DataType::INT64);
-    arg_message->add_int64value((uintptr_t)message);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPushDebugGroupKHR(source, id, length, message);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) message,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPopDebugGroupKHR(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPopDebugGroupKHR);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPopDebugGroupKHR();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glObjectLabelKHR(GLenum identifier, GLuint name, GLsizei length, const GLchar * label) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glObjectLabelKHR);
-
-    // copy argument identifier
-    GLMessage_DataType *arg_identifier = glmsg.add_args();
-    arg_identifier->set_isarray(false);
-    arg_identifier->set_type(GLMessage::DataType::ENUM);
-    arg_identifier->add_intvalue((int)identifier);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT);
-    arg_name->add_intvalue(name);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument label
-    GLMessage_DataType *arg_label = glmsg.add_args();
-    arg_label->set_isarray(false);
-    arg_label->set_type(GLMessage::DataType::INT64);
-    arg_label->add_int64value((uintptr_t)label);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glObjectLabelKHR(identifier, name, length, label);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) label,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetObjectLabelKHR(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetObjectLabelKHR);
-
-    // copy argument identifier
-    GLMessage_DataType *arg_identifier = glmsg.add_args();
-    arg_identifier->set_isarray(false);
-    arg_identifier->set_type(GLMessage::DataType::ENUM);
-    arg_identifier->add_intvalue((int)identifier);
-
-    // copy argument name
-    GLMessage_DataType *arg_name = glmsg.add_args();
-    arg_name->set_isarray(false);
-    arg_name->set_type(GLMessage::DataType::INT);
-    arg_name->add_intvalue(name);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument label
-    GLMessage_DataType *arg_label = glmsg.add_args();
-    arg_label->set_isarray(false);
-    arg_label->set_type(GLMessage::DataType::INT64);
-    arg_label->add_int64value((uintptr_t)label);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetObjectLabelKHR(identifier, name, bufSize, length, label);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) label,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glObjectPtrLabelKHR(const void * ptr, GLsizei length, const GLchar * label) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glObjectPtrLabelKHR);
-
-    // copy argument ptr
-    GLMessage_DataType *arg_ptr = glmsg.add_args();
-    arg_ptr->set_isarray(false);
-    arg_ptr->set_type(GLMessage::DataType::INT64);
-    arg_ptr->add_int64value((uintptr_t)ptr);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument label
-    GLMessage_DataType *arg_label = glmsg.add_args();
-    arg_label->set_isarray(false);
-    arg_label->set_type(GLMessage::DataType::INT64);
-    arg_label->add_int64value((uintptr_t)label);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glObjectPtrLabelKHR(ptr, length, label);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ptr,
-        (void *) label,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetObjectPtrLabelKHR(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetObjectPtrLabelKHR);
-
-    // copy argument ptr
-    GLMessage_DataType *arg_ptr = glmsg.add_args();
-    arg_ptr->set_isarray(false);
-    arg_ptr->set_type(GLMessage::DataType::INT64);
-    arg_ptr->add_int64value((uintptr_t)ptr);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument label
-    GLMessage_DataType *arg_label = glmsg.add_args();
-    arg_label->set_isarray(false);
-    arg_label->set_type(GLMessage::DataType::INT64);
-    arg_label->add_int64value((uintptr_t)label);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetObjectPtrLabelKHR(ptr, bufSize, length, label);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ptr,
-        (void *) length,
-        (void *) label,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPointervKHR(GLenum pname, void ** params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPointervKHR);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPointervKHR(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEGLImageTargetTexture2DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument image
-    GLMessage_DataType *arg_image = glmsg.add_args();
-    arg_image->set_isarray(false);
-    arg_image->set_type(GLMessage::DataType::INT64);
-    arg_image->add_int64value((uintptr_t)image);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEGLImageTargetTexture2DOES(target, image);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) image,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEGLImageTargetRenderbufferStorageOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument image
-    GLMessage_DataType *arg_image = glmsg.add_args();
-    arg_image->set_isarray(false);
-    arg_image->set_type(GLMessage::DataType::INT64);
-    arg_image->add_int64value((uintptr_t)image);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEGLImageTargetRenderbufferStorageOES(target, image);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) image,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramBinaryOES);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument binaryFormat
-    GLMessage_DataType *arg_binaryFormat = glmsg.add_args();
-    arg_binaryFormat->set_isarray(false);
-    arg_binaryFormat->set_type(GLMessage::DataType::INT64);
-    arg_binaryFormat->add_int64value((uintptr_t)binaryFormat);
-
-    // copy argument binary
-    GLMessage_DataType *arg_binary = glmsg.add_args();
-    arg_binary->set_isarray(false);
-    arg_binary->set_type(GLMessage::DataType::INT64);
-    arg_binary->add_int64value((uintptr_t)binary);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramBinaryOES(program, bufSize, length, binaryFormat, binary);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) binaryFormat,
-        (void *) binary,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramBinaryOES(GLuint program, GLenum binaryFormat, const void * binary, GLint length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramBinaryOES);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument binaryFormat
-    GLMessage_DataType *arg_binaryFormat = glmsg.add_args();
-    arg_binaryFormat->set_isarray(false);
-    arg_binaryFormat->set_type(GLMessage::DataType::ENUM);
-    arg_binaryFormat->add_intvalue((int)binaryFormat);
-
-    // copy argument binary
-    GLMessage_DataType *arg_binary = glmsg.add_args();
-    arg_binary->set_isarray(false);
-    arg_binary->set_type(GLMessage::DataType::INT64);
-    arg_binary->add_int64value((uintptr_t)binary);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramBinaryOES(program, binaryFormat, binary, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) binary,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void * GLTrace_glMapBufferOES(GLenum target, GLenum access) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMapBufferOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument access
-    GLMessage_DataType *arg_access = glmsg.add_args();
-    arg_access->set_isarray(false);
-    arg_access->set_type(GLMessage::DataType::ENUM);
-    arg_access->add_intvalue((int)access);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    void * retValue = glContext->hooks->gl.glMapBufferOES(target, access);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glUnmapBufferOES(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUnmapBufferOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glUnmapBufferOES(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetBufferPointervOES(GLenum target, GLenum pname, void ** params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetBufferPointervOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetBufferPointervOES(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMinSampleShadingOES(GLfloat value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMinSampleShadingOES);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::FLOAT);
-    arg_value->add_floatvalue(value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMinSampleShadingOES(value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexImage3DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexImage3DOES(target, level, internalformat, width, height, depth, border, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexSubImage3DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument pixels
-    GLMessage_DataType *arg_pixels = glmsg.add_args();
-    arg_pixels->set_isarray(false);
-    arg_pixels->set_type(GLMessage::DataType::INT64);
-    arg_pixels->add_int64value((uintptr_t)pixels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexSubImage3DOES(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pixels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyTexSubImage3DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyTexSubImage3DOES(target, level, xoffset, yoffset, zoffset, x, y, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompressedTexImage3DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument border
-    GLMessage_DataType *arg_border = glmsg.add_args();
-    arg_border->set_isarray(false);
-    arg_border->set_type(GLMessage::DataType::INT);
-    arg_border->add_intvalue(border);
-
-    // copy argument imageSize
-    GLMessage_DataType *arg_imageSize = glmsg.add_args();
-    arg_imageSize->set_isarray(false);
-    arg_imageSize->set_type(GLMessage::DataType::INT);
-    arg_imageSize->add_intvalue(imageSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompressedTexImage3DOES(target, level, internalformat, width, height, depth, border, imageSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCompressedTexSubImage3DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument imageSize
-    GLMessage_DataType *arg_imageSize = glmsg.add_args();
-    arg_imageSize->set_isarray(false);
-    arg_imageSize->set_type(GLMessage::DataType::INT);
-    arg_imageSize->add_intvalue(imageSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCompressedTexSubImage3DOES(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTexture3DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument textarget
-    GLMessage_DataType *arg_textarget = glmsg.add_args();
-    arg_textarget->set_isarray(false);
-    arg_textarget->set_type(GLMessage::DataType::ENUM);
-    arg_textarget->add_intvalue((int)textarget);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTexture3DOES(target, attachment, textarget, texture, level, zoffset);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage3DMultisampleOES(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage3DMultisampleOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument fixedsamplelocations
-    GLMessage_DataType *arg_fixedsamplelocations = glmsg.add_args();
-    arg_fixedsamplelocations->set_isarray(false);
-    arg_fixedsamplelocations->set_type(GLMessage::DataType::BOOL);
-    arg_fixedsamplelocations->add_boolvalue(fixedsamplelocations);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage3DMultisampleOES(target, samples, internalformat, width, height, depth, fixedsamplelocations);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindVertexArrayOES(GLuint array) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindVertexArrayOES);
-
-    // copy argument array
-    GLMessage_DataType *arg_array = glmsg.add_args();
-    arg_array->set_isarray(false);
-    arg_array->set_type(GLMessage::DataType::INT);
-    arg_array->add_intvalue(array);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindVertexArrayOES(array);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteVertexArraysOES(GLsizei n, const GLuint * arrays) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteVertexArraysOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument arrays
-    GLMessage_DataType *arg_arrays = glmsg.add_args();
-    arg_arrays->set_isarray(false);
-    arg_arrays->set_type(GLMessage::DataType::INT64);
-    arg_arrays->add_int64value((uintptr_t)arrays);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteVertexArraysOES(n, arrays);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) arrays,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenVertexArraysOES(GLsizei n, GLuint * arrays) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenVertexArraysOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument arrays
-    GLMessage_DataType *arg_arrays = glmsg.add_args();
-    arg_arrays->set_isarray(false);
-    arg_arrays->set_type(GLMessage::DataType::INT64);
-    arg_arrays->add_int64value((uintptr_t)arrays);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenVertexArraysOES(n, arrays);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) arrays,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsVertexArrayOES(GLuint array) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsVertexArrayOES);
-
-    // copy argument array
-    GLMessage_DataType *arg_array = glmsg.add_args();
-    arg_array->set_isarray(false);
-    arg_array->set_type(GLMessage::DataType::INT);
-    arg_array->add_intvalue(array);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsVertexArrayOES(array);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetPerfMonitorGroupsAMD(GLint * numGroups, GLsizei groupsSize, GLuint * groups) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfMonitorGroupsAMD);
-
-    // copy argument numGroups
-    GLMessage_DataType *arg_numGroups = glmsg.add_args();
-    arg_numGroups->set_isarray(false);
-    arg_numGroups->set_type(GLMessage::DataType::INT64);
-    arg_numGroups->add_int64value((uintptr_t)numGroups);
-
-    // copy argument groupsSize
-    GLMessage_DataType *arg_groupsSize = glmsg.add_args();
-    arg_groupsSize->set_isarray(false);
-    arg_groupsSize->set_type(GLMessage::DataType::INT);
-    arg_groupsSize->add_intvalue(groupsSize);
-
-    // copy argument groups
-    GLMessage_DataType *arg_groups = glmsg.add_args();
-    arg_groups->set_isarray(false);
-    arg_groups->set_type(GLMessage::DataType::INT64);
-    arg_groups->add_int64value((uintptr_t)groups);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfMonitorGroupsAMD(numGroups, groupsSize, groups);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) numGroups,
-        (void *) groups,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfMonitorCountersAMD(GLuint group, GLint * numCounters, GLint * maxActiveCounters, GLsizei counterSize, GLuint * counters) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfMonitorCountersAMD);
-
-    // copy argument group
-    GLMessage_DataType *arg_group = glmsg.add_args();
-    arg_group->set_isarray(false);
-    arg_group->set_type(GLMessage::DataType::INT);
-    arg_group->add_intvalue(group);
-
-    // copy argument numCounters
-    GLMessage_DataType *arg_numCounters = glmsg.add_args();
-    arg_numCounters->set_isarray(false);
-    arg_numCounters->set_type(GLMessage::DataType::INT64);
-    arg_numCounters->add_int64value((uintptr_t)numCounters);
-
-    // copy argument maxActiveCounters
-    GLMessage_DataType *arg_maxActiveCounters = glmsg.add_args();
-    arg_maxActiveCounters->set_isarray(false);
-    arg_maxActiveCounters->set_type(GLMessage::DataType::INT64);
-    arg_maxActiveCounters->add_int64value((uintptr_t)maxActiveCounters);
-
-    // copy argument counterSize
-    GLMessage_DataType *arg_counterSize = glmsg.add_args();
-    arg_counterSize->set_isarray(false);
-    arg_counterSize->set_type(GLMessage::DataType::INT);
-    arg_counterSize->add_intvalue(counterSize);
-
-    // copy argument counters
-    GLMessage_DataType *arg_counters = glmsg.add_args();
-    arg_counters->set_isarray(false);
-    arg_counters->set_type(GLMessage::DataType::INT64);
-    arg_counters->add_int64value((uintptr_t)counters);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfMonitorCountersAMD(group, numCounters, maxActiveCounters, counterSize, counters);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) numCounters,
-        (void *) maxActiveCounters,
-        (void *) counters,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, GLsizei * length, GLchar * groupString) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfMonitorGroupStringAMD);
-
-    // copy argument group
-    GLMessage_DataType *arg_group = glmsg.add_args();
-    arg_group->set_isarray(false);
-    arg_group->set_type(GLMessage::DataType::INT);
-    arg_group->add_intvalue(group);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument groupString
-    GLMessage_DataType *arg_groupString = glmsg.add_args();
-    arg_groupString->set_isarray(false);
-    arg_groupString->set_type(GLMessage::DataType::INT64);
-    arg_groupString->add_int64value((uintptr_t)groupString);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfMonitorGroupStringAMD(group, bufSize, length, groupString);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) groupString,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, GLsizei bufSize, GLsizei * length, GLchar * counterString) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfMonitorCounterStringAMD);
-
-    // copy argument group
-    GLMessage_DataType *arg_group = glmsg.add_args();
-    arg_group->set_isarray(false);
-    arg_group->set_type(GLMessage::DataType::INT);
-    arg_group->add_intvalue(group);
-
-    // copy argument counter
-    GLMessage_DataType *arg_counter = glmsg.add_args();
-    arg_counter->set_isarray(false);
-    arg_counter->set_type(GLMessage::DataType::INT);
-    arg_counter->add_intvalue(counter);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument counterString
-    GLMessage_DataType *arg_counterString = glmsg.add_args();
-    arg_counterString->set_isarray(false);
-    arg_counterString->set_type(GLMessage::DataType::INT64);
-    arg_counterString->add_int64value((uintptr_t)counterString);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfMonitorCounterStringAMD(group, counter, bufSize, length, counterString);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) counterString,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum pname, void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfMonitorCounterInfoAMD);
-
-    // copy argument group
-    GLMessage_DataType *arg_group = glmsg.add_args();
-    arg_group->set_isarray(false);
-    arg_group->set_type(GLMessage::DataType::INT);
-    arg_group->add_intvalue(group);
-
-    // copy argument counter
-    GLMessage_DataType *arg_counter = glmsg.add_args();
-    arg_counter->set_isarray(false);
-    arg_counter->set_type(GLMessage::DataType::INT);
-    arg_counter->add_intvalue(counter);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfMonitorCounterInfoAMD(group, counter, pname, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenPerfMonitorsAMD(GLsizei n, GLuint * monitors) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenPerfMonitorsAMD);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument monitors
-    GLMessage_DataType *arg_monitors = glmsg.add_args();
-    arg_monitors->set_isarray(false);
-    arg_monitors->set_type(GLMessage::DataType::INT64);
-    arg_monitors->add_int64value((uintptr_t)monitors);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenPerfMonitorsAMD(n, monitors);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) monitors,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeletePerfMonitorsAMD(GLsizei n, GLuint * monitors) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeletePerfMonitorsAMD);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument monitors
-    GLMessage_DataType *arg_monitors = glmsg.add_args();
-    arg_monitors->set_isarray(false);
-    arg_monitors->set_type(GLMessage::DataType::INT64);
-    arg_monitors->add_int64value((uintptr_t)monitors);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeletePerfMonitorsAMD(n, monitors);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) monitors,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint * counterList) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSelectPerfMonitorCountersAMD);
-
-    // copy argument monitor
-    GLMessage_DataType *arg_monitor = glmsg.add_args();
-    arg_monitor->set_isarray(false);
-    arg_monitor->set_type(GLMessage::DataType::INT);
-    arg_monitor->add_intvalue(monitor);
-
-    // copy argument enable
-    GLMessage_DataType *arg_enable = glmsg.add_args();
-    arg_enable->set_isarray(false);
-    arg_enable->set_type(GLMessage::DataType::BOOL);
-    arg_enable->add_boolvalue(enable);
-
-    // copy argument group
-    GLMessage_DataType *arg_group = glmsg.add_args();
-    arg_group->set_isarray(false);
-    arg_group->set_type(GLMessage::DataType::INT);
-    arg_group->add_intvalue(group);
-
-    // copy argument numCounters
-    GLMessage_DataType *arg_numCounters = glmsg.add_args();
-    arg_numCounters->set_isarray(false);
-    arg_numCounters->set_type(GLMessage::DataType::INT);
-    arg_numCounters->add_intvalue(numCounters);
-
-    // copy argument counterList
-    GLMessage_DataType *arg_counterList = glmsg.add_args();
-    arg_counterList->set_isarray(false);
-    arg_counterList->set_type(GLMessage::DataType::INT64);
-    arg_counterList->add_int64value((uintptr_t)counterList);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSelectPerfMonitorCountersAMD(monitor, enable, group, numCounters, counterList);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) counterList,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBeginPerfMonitorAMD(GLuint monitor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBeginPerfMonitorAMD);
-
-    // copy argument monitor
-    GLMessage_DataType *arg_monitor = glmsg.add_args();
-    arg_monitor->set_isarray(false);
-    arg_monitor->set_type(GLMessage::DataType::INT);
-    arg_monitor->add_intvalue(monitor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBeginPerfMonitorAMD(monitor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEndPerfMonitorAMD(GLuint monitor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEndPerfMonitorAMD);
-
-    // copy argument monitor
-    GLMessage_DataType *arg_monitor = glmsg.add_args();
-    arg_monitor->set_isarray(false);
-    arg_monitor->set_type(GLMessage::DataType::INT);
-    arg_monitor->add_intvalue(monitor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEndPerfMonitorAMD(monitor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint * data, GLint * bytesWritten) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfMonitorCounterDataAMD);
-
-    // copy argument monitor
-    GLMessage_DataType *arg_monitor = glmsg.add_args();
-    arg_monitor->set_isarray(false);
-    arg_monitor->set_type(GLMessage::DataType::INT);
-    arg_monitor->add_intvalue(monitor);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument dataSize
-    GLMessage_DataType *arg_dataSize = glmsg.add_args();
-    arg_dataSize->set_isarray(false);
-    arg_dataSize->set_type(GLMessage::DataType::INT);
-    arg_dataSize->add_intvalue(dataSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // copy argument bytesWritten
-    GLMessage_DataType *arg_bytesWritten = glmsg.add_args();
-    arg_bytesWritten->set_isarray(false);
-    arg_bytesWritten->set_type(GLMessage::DataType::INT64);
-    arg_bytesWritten->add_int64value((uintptr_t)bytesWritten);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfMonitorCounterDataAMD(monitor, pname, dataSize, data, bytesWritten);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-        (void *) bytesWritten,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlitFramebufferANGLE);
-
-    // copy argument srcX0
-    GLMessage_DataType *arg_srcX0 = glmsg.add_args();
-    arg_srcX0->set_isarray(false);
-    arg_srcX0->set_type(GLMessage::DataType::INT);
-    arg_srcX0->add_intvalue(srcX0);
-
-    // copy argument srcY0
-    GLMessage_DataType *arg_srcY0 = glmsg.add_args();
-    arg_srcY0->set_isarray(false);
-    arg_srcY0->set_type(GLMessage::DataType::INT);
-    arg_srcY0->add_intvalue(srcY0);
-
-    // copy argument srcX1
-    GLMessage_DataType *arg_srcX1 = glmsg.add_args();
-    arg_srcX1->set_isarray(false);
-    arg_srcX1->set_type(GLMessage::DataType::INT);
-    arg_srcX1->add_intvalue(srcX1);
-
-    // copy argument srcY1
-    GLMessage_DataType *arg_srcY1 = glmsg.add_args();
-    arg_srcY1->set_isarray(false);
-    arg_srcY1->set_type(GLMessage::DataType::INT);
-    arg_srcY1->add_intvalue(srcY1);
-
-    // copy argument dstX0
-    GLMessage_DataType *arg_dstX0 = glmsg.add_args();
-    arg_dstX0->set_isarray(false);
-    arg_dstX0->set_type(GLMessage::DataType::INT);
-    arg_dstX0->add_intvalue(dstX0);
-
-    // copy argument dstY0
-    GLMessage_DataType *arg_dstY0 = glmsg.add_args();
-    arg_dstY0->set_isarray(false);
-    arg_dstY0->set_type(GLMessage::DataType::INT);
-    arg_dstY0->add_intvalue(dstY0);
-
-    // copy argument dstX1
-    GLMessage_DataType *arg_dstX1 = glmsg.add_args();
-    arg_dstX1->set_isarray(false);
-    arg_dstX1->set_type(GLMessage::DataType::INT);
-    arg_dstX1->add_intvalue(dstX1);
-
-    // copy argument dstY1
-    GLMessage_DataType *arg_dstY1 = glmsg.add_args();
-    arg_dstY1->set_isarray(false);
-    arg_dstY1->set_type(GLMessage::DataType::INT);
-    arg_dstY1->add_intvalue(dstY1);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // copy argument filter
-    GLMessage_DataType *arg_filter = glmsg.add_args();
-    arg_filter->set_isarray(false);
-    arg_filter->set_type(GLMessage::DataType::ENUM);
-    arg_filter->add_intvalue((int)filter);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageMultisampleANGLE);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawArraysInstancedANGLE);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument first
-    GLMessage_DataType *arg_first = glmsg.add_args();
-    arg_first->set_isarray(false);
-    arg_first->set_type(GLMessage::DataType::INT);
-    arg_first->add_intvalue(first);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawArraysInstancedANGLE(mode, first, count, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawElementsInstancedANGLE);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawElementsInstancedANGLE(mode, count, type, indices, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribDivisorANGLE);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument divisor
-    GLMessage_DataType *arg_divisor = glmsg.add_args();
-    arg_divisor->set_isarray(false);
-    arg_divisor->set_type(GLMessage::DataType::INT);
-    arg_divisor->add_intvalue(divisor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribDivisorANGLE(index, divisor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei * length, GLchar * source) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTranslatedShaderSourceANGLE);
-
-    // copy argument shader
-    GLMessage_DataType *arg_shader = glmsg.add_args();
-    arg_shader->set_isarray(false);
-    arg_shader->set_type(GLMessage::DataType::INT);
-    arg_shader->add_intvalue(shader);
-
-    // copy argument bufsize
-    GLMessage_DataType *arg_bufsize = glmsg.add_args();
-    arg_bufsize->set_isarray(false);
-    arg_bufsize->set_type(GLMessage::DataType::INT);
-    arg_bufsize->add_intvalue(bufsize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument source
-    GLMessage_DataType *arg_source = glmsg.add_args();
-    arg_source->set_isarray(false);
-    arg_source->set_type(GLMessage::DataType::INT64);
-    arg_source->add_int64value((uintptr_t)source);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTranslatedShaderSourceANGLE(shader, bufsize, length, source);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) source,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyTextureLevelsAPPLE(GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyTextureLevelsAPPLE);
-
-    // copy argument destinationTexture
-    GLMessage_DataType *arg_destinationTexture = glmsg.add_args();
-    arg_destinationTexture->set_isarray(false);
-    arg_destinationTexture->set_type(GLMessage::DataType::INT);
-    arg_destinationTexture->add_intvalue(destinationTexture);
-
-    // copy argument sourceTexture
-    GLMessage_DataType *arg_sourceTexture = glmsg.add_args();
-    arg_sourceTexture->set_isarray(false);
-    arg_sourceTexture->set_type(GLMessage::DataType::INT);
-    arg_sourceTexture->add_intvalue(sourceTexture);
-
-    // copy argument sourceBaseLevel
-    GLMessage_DataType *arg_sourceBaseLevel = glmsg.add_args();
-    arg_sourceBaseLevel->set_isarray(false);
-    arg_sourceBaseLevel->set_type(GLMessage::DataType::INT);
-    arg_sourceBaseLevel->add_intvalue(sourceBaseLevel);
-
-    // copy argument sourceLevelCount
-    GLMessage_DataType *arg_sourceLevelCount = glmsg.add_args();
-    arg_sourceLevelCount->set_isarray(false);
-    arg_sourceLevelCount->set_type(GLMessage::DataType::INT);
-    arg_sourceLevelCount->add_intvalue(sourceLevelCount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyTextureLevelsAPPLE(destinationTexture, sourceTexture, sourceBaseLevel, sourceLevelCount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageMultisampleAPPLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageMultisampleAPPLE);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageMultisampleAPPLE(target, samples, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glResolveMultisampleFramebufferAPPLE(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glResolveMultisampleFramebufferAPPLE);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glResolveMultisampleFramebufferAPPLE();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLsync GLTrace_glFenceSyncAPPLE(GLenum condition, GLbitfield flags) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFenceSyncAPPLE);
-
-    // copy argument condition
-    GLMessage_DataType *arg_condition = glmsg.add_args();
-    arg_condition->set_isarray(false);
-    arg_condition->set_type(GLMessage::DataType::ENUM);
-    arg_condition->add_intvalue((int)condition);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLsync retValue = glContext->hooks->gl.glFenceSyncAPPLE(condition, flags);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glIsSyncAPPLE(GLsync sync) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsSyncAPPLE);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsSyncAPPLE(sync);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glDeleteSyncAPPLE(GLsync sync) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteSyncAPPLE);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteSyncAPPLE(sync);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLenum GLTrace_glClientWaitSyncAPPLE(GLsync sync, GLbitfield flags, GLuint64 timeout) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClientWaitSyncAPPLE);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // copy argument timeout
-    GLMessage_DataType *arg_timeout = glmsg.add_args();
-    arg_timeout->set_isarray(false);
-    arg_timeout->set_type(GLMessage::DataType::INT64);
-    arg_timeout->add_int64value(timeout);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLenum retValue = glContext->hooks->gl.glClientWaitSyncAPPLE(sync, flags, timeout);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::ENUM);
-    rt->add_intvalue((int)retValue);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glWaitSyncAPPLE(GLsync sync, GLbitfield flags, GLuint64 timeout) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glWaitSyncAPPLE);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // copy argument timeout
-    GLMessage_DataType *arg_timeout = glmsg.add_args();
-    arg_timeout->set_isarray(false);
-    arg_timeout->set_type(GLMessage::DataType::INT64);
-    arg_timeout->add_int64value(timeout);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glWaitSyncAPPLE(sync, flags, timeout);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetInteger64vAPPLE(GLenum pname, GLint64 * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetInteger64vAPPLE);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetInteger64vAPPLE(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetSyncivAPPLE(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetSyncivAPPLE);
-
-    // copy argument sync
-    GLMessage_DataType *arg_sync = glmsg.add_args();
-    arg_sync->set_isarray(false);
-    arg_sync->set_type(GLMessage::DataType::INT64);
-    arg_sync->add_int64value((uintptr_t)sync);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument values
-    GLMessage_DataType *arg_values = glmsg.add_args();
-    arg_values->set_isarray(false);
-    arg_values->set_type(GLMessage::DataType::INT64);
-    arg_values->add_int64value((uintptr_t)values);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetSyncivAPPLE(sync, pname, bufSize, length, values);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) sync,
-        (void *) length,
-        (void *) values,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyImageSubDataEXT(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyImageSubDataEXT);
-
-    // copy argument srcName
-    GLMessage_DataType *arg_srcName = glmsg.add_args();
-    arg_srcName->set_isarray(false);
-    arg_srcName->set_type(GLMessage::DataType::INT);
-    arg_srcName->add_intvalue(srcName);
-
-    // copy argument srcTarget
-    GLMessage_DataType *arg_srcTarget = glmsg.add_args();
-    arg_srcTarget->set_isarray(false);
-    arg_srcTarget->set_type(GLMessage::DataType::ENUM);
-    arg_srcTarget->add_intvalue((int)srcTarget);
-
-    // copy argument srcLevel
-    GLMessage_DataType *arg_srcLevel = glmsg.add_args();
-    arg_srcLevel->set_isarray(false);
-    arg_srcLevel->set_type(GLMessage::DataType::INT);
-    arg_srcLevel->add_intvalue(srcLevel);
-
-    // copy argument srcX
-    GLMessage_DataType *arg_srcX = glmsg.add_args();
-    arg_srcX->set_isarray(false);
-    arg_srcX->set_type(GLMessage::DataType::INT);
-    arg_srcX->add_intvalue(srcX);
-
-    // copy argument srcY
-    GLMessage_DataType *arg_srcY = glmsg.add_args();
-    arg_srcY->set_isarray(false);
-    arg_srcY->set_type(GLMessage::DataType::INT);
-    arg_srcY->add_intvalue(srcY);
-
-    // copy argument srcZ
-    GLMessage_DataType *arg_srcZ = glmsg.add_args();
-    arg_srcZ->set_isarray(false);
-    arg_srcZ->set_type(GLMessage::DataType::INT);
-    arg_srcZ->add_intvalue(srcZ);
-
-    // copy argument dstName
-    GLMessage_DataType *arg_dstName = glmsg.add_args();
-    arg_dstName->set_isarray(false);
-    arg_dstName->set_type(GLMessage::DataType::INT);
-    arg_dstName->add_intvalue(dstName);
-
-    // copy argument dstTarget
-    GLMessage_DataType *arg_dstTarget = glmsg.add_args();
-    arg_dstTarget->set_isarray(false);
-    arg_dstTarget->set_type(GLMessage::DataType::ENUM);
-    arg_dstTarget->add_intvalue((int)dstTarget);
-
-    // copy argument dstLevel
-    GLMessage_DataType *arg_dstLevel = glmsg.add_args();
-    arg_dstLevel->set_isarray(false);
-    arg_dstLevel->set_type(GLMessage::DataType::INT);
-    arg_dstLevel->add_intvalue(dstLevel);
-
-    // copy argument dstX
-    GLMessage_DataType *arg_dstX = glmsg.add_args();
-    arg_dstX->set_isarray(false);
-    arg_dstX->set_type(GLMessage::DataType::INT);
-    arg_dstX->add_intvalue(dstX);
-
-    // copy argument dstY
-    GLMessage_DataType *arg_dstY = glmsg.add_args();
-    arg_dstY->set_isarray(false);
-    arg_dstY->set_type(GLMessage::DataType::INT);
-    arg_dstY->add_intvalue(dstY);
-
-    // copy argument dstZ
-    GLMessage_DataType *arg_dstZ = glmsg.add_args();
-    arg_dstZ->set_isarray(false);
-    arg_dstZ->set_type(GLMessage::DataType::INT);
-    arg_dstZ->add_intvalue(dstZ);
-
-    // copy argument srcWidth
-    GLMessage_DataType *arg_srcWidth = glmsg.add_args();
-    arg_srcWidth->set_isarray(false);
-    arg_srcWidth->set_type(GLMessage::DataType::INT);
-    arg_srcWidth->add_intvalue(srcWidth);
-
-    // copy argument srcHeight
-    GLMessage_DataType *arg_srcHeight = glmsg.add_args();
-    arg_srcHeight->set_isarray(false);
-    arg_srcHeight->set_type(GLMessage::DataType::INT);
-    arg_srcHeight->add_intvalue(srcHeight);
-
-    // copy argument srcDepth
-    GLMessage_DataType *arg_srcDepth = glmsg.add_args();
-    arg_srcDepth->set_isarray(false);
-    arg_srcDepth->set_type(GLMessage::DataType::INT);
-    arg_srcDepth->add_intvalue(srcDepth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyImageSubDataEXT(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLabelObjectEXT(GLenum type, GLuint object, GLsizei length, const GLchar * label) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLabelObjectEXT);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument object
-    GLMessage_DataType *arg_object = glmsg.add_args();
-    arg_object->set_isarray(false);
-    arg_object->set_type(GLMessage::DataType::INT);
-    arg_object->add_intvalue(object);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument label
-    GLMessage_DataType *arg_label = glmsg.add_args();
-    arg_label->set_isarray(false);
-    arg_label->set_type(GLMessage::DataType::INT64);
-    arg_label->add_int64value((uintptr_t)label);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLabelObjectEXT(type, object, length, label);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) label,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetObjectLabelEXT(GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetObjectLabelEXT);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument object
-    GLMessage_DataType *arg_object = glmsg.add_args();
-    arg_object->set_isarray(false);
-    arg_object->set_type(GLMessage::DataType::INT);
-    arg_object->add_intvalue(object);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument label
-    GLMessage_DataType *arg_label = glmsg.add_args();
-    arg_label->set_isarray(false);
-    arg_label->set_type(GLMessage::DataType::INT64);
-    arg_label->add_int64value((uintptr_t)label);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetObjectLabelEXT(type, object, bufSize, length, label);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) label,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glInsertEventMarkerEXT(GLsizei length, const GLchar * marker) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glInsertEventMarkerEXT);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument marker
-    GLMessage_DataType *arg_marker = glmsg.add_args();
-    arg_marker->set_isarray(false);
-    arg_marker->set_type(GLMessage::DataType::INT64);
-    arg_marker->add_int64value((uintptr_t)marker);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glInsertEventMarkerEXT(length, marker);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) marker,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPushGroupMarkerEXT(GLsizei length, const GLchar * marker) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPushGroupMarkerEXT);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument marker
-    GLMessage_DataType *arg_marker = glmsg.add_args();
-    arg_marker->set_isarray(false);
-    arg_marker->set_type(GLMessage::DataType::INT64);
-    arg_marker->add_int64value((uintptr_t)marker);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPushGroupMarkerEXT(length, marker);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) marker,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPopGroupMarkerEXT(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPopGroupMarkerEXT);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPopGroupMarkerEXT();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum * attachments) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDiscardFramebufferEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument numAttachments
-    GLMessage_DataType *arg_numAttachments = glmsg.add_args();
-    arg_numAttachments->set_isarray(false);
-    arg_numAttachments->set_type(GLMessage::DataType::INT);
-    arg_numAttachments->add_intvalue(numAttachments);
-
-    // copy argument attachments
-    GLMessage_DataType *arg_attachments = glmsg.add_args();
-    arg_attachments->set_isarray(false);
-    arg_attachments->set_type(GLMessage::DataType::INT64);
-    arg_attachments->add_int64value((uintptr_t)attachments);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDiscardFramebufferEXT(target, numAttachments, attachments);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) attachments,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenQueriesEXT(GLsizei n, GLuint * ids) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenQueriesEXT);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenQueriesEXT(n, ids);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteQueriesEXT(GLsizei n, const GLuint * ids) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteQueriesEXT);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument ids
-    GLMessage_DataType *arg_ids = glmsg.add_args();
-    arg_ids->set_isarray(false);
-    arg_ids->set_type(GLMessage::DataType::INT64);
-    arg_ids->add_int64value((uintptr_t)ids);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteQueriesEXT(n, ids);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) ids,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsQueryEXT(GLuint id) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsQueryEXT);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsQueryEXT(id);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glBeginQueryEXT(GLenum target, GLuint id) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBeginQueryEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBeginQueryEXT(target, id);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEndQueryEXT(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEndQueryEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEndQueryEXT(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glQueryCounterEXT(GLuint id, GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glQueryCounterEXT);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glQueryCounterEXT(id, target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryivEXT(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryivEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryivEXT(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryObjectivEXT(GLuint id, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryObjectivEXT);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryObjectivEXT(id, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryObjectuivEXT);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryObjectuivEXT(id, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryObjecti64vEXT);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryObjecti64vEXT(id, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetQueryObjectui64vEXT);
-
-    // copy argument id
-    GLMessage_DataType *arg_id = glmsg.add_args();
-    arg_id->set_isarray(false);
-    arg_id->set_type(GLMessage::DataType::INT);
-    arg_id->add_intvalue(id);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetQueryObjectui64vEXT(id, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawBuffersEXT(GLsizei n, const GLenum * bufs) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawBuffersEXT);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument bufs
-    GLMessage_DataType *arg_bufs = glmsg.add_args();
-    arg_bufs->set_isarray(false);
-    arg_bufs->set_type(GLMessage::DataType::INT64);
-    arg_bufs->add_int64value((uintptr_t)bufs);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawBuffersEXT(n, bufs);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) bufs,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEnableiEXT(GLenum target, GLuint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEnableiEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEnableiEXT(target, index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDisableiEXT(GLenum target, GLuint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDisableiEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDisableiEXT(target, index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendEquationiEXT(GLuint buf, GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendEquationiEXT);
-
-    // copy argument buf
-    GLMessage_DataType *arg_buf = glmsg.add_args();
-    arg_buf->set_isarray(false);
-    arg_buf->set_type(GLMessage::DataType::INT);
-    arg_buf->add_intvalue(buf);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendEquationiEXT(buf, mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendEquationSeparateiEXT(GLuint buf, GLenum modeRGB, GLenum modeAlpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendEquationSeparateiEXT);
-
-    // copy argument buf
-    GLMessage_DataType *arg_buf = glmsg.add_args();
-    arg_buf->set_isarray(false);
-    arg_buf->set_type(GLMessage::DataType::INT);
-    arg_buf->add_intvalue(buf);
-
-    // copy argument modeRGB
-    GLMessage_DataType *arg_modeRGB = glmsg.add_args();
-    arg_modeRGB->set_isarray(false);
-    arg_modeRGB->set_type(GLMessage::DataType::ENUM);
-    arg_modeRGB->add_intvalue((int)modeRGB);
-
-    // copy argument modeAlpha
-    GLMessage_DataType *arg_modeAlpha = glmsg.add_args();
-    arg_modeAlpha->set_isarray(false);
-    arg_modeAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_modeAlpha->add_intvalue((int)modeAlpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendEquationSeparateiEXT(buf, modeRGB, modeAlpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendFunciEXT(GLuint buf, GLenum src, GLenum dst) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendFunciEXT);
-
-    // copy argument buf
-    GLMessage_DataType *arg_buf = glmsg.add_args();
-    arg_buf->set_isarray(false);
-    arg_buf->set_type(GLMessage::DataType::INT);
-    arg_buf->add_intvalue(buf);
-
-    // copy argument src
-    GLMessage_DataType *arg_src = glmsg.add_args();
-    arg_src->set_isarray(false);
-    arg_src->set_type(GLMessage::DataType::ENUM);
-    arg_src->add_intvalue((int)src);
-
-    // copy argument dst
-    GLMessage_DataType *arg_dst = glmsg.add_args();
-    arg_dst->set_isarray(false);
-    arg_dst->set_type(GLMessage::DataType::ENUM);
-    arg_dst->add_intvalue((int)dst);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendFunciEXT(buf, src, dst);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendFuncSeparateiEXT(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendFuncSeparateiEXT);
-
-    // copy argument buf
-    GLMessage_DataType *arg_buf = glmsg.add_args();
-    arg_buf->set_isarray(false);
-    arg_buf->set_type(GLMessage::DataType::INT);
-    arg_buf->add_intvalue(buf);
-
-    // copy argument srcRGB
-    GLMessage_DataType *arg_srcRGB = glmsg.add_args();
-    arg_srcRGB->set_isarray(false);
-    arg_srcRGB->set_type(GLMessage::DataType::ENUM);
-    arg_srcRGB->add_intvalue((int)srcRGB);
-
-    // copy argument dstRGB
-    GLMessage_DataType *arg_dstRGB = glmsg.add_args();
-    arg_dstRGB->set_isarray(false);
-    arg_dstRGB->set_type(GLMessage::DataType::ENUM);
-    arg_dstRGB->add_intvalue((int)dstRGB);
-
-    // copy argument srcAlpha
-    GLMessage_DataType *arg_srcAlpha = glmsg.add_args();
-    arg_srcAlpha->set_isarray(false);
-    arg_srcAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_srcAlpha->add_intvalue((int)srcAlpha);
-
-    // copy argument dstAlpha
-    GLMessage_DataType *arg_dstAlpha = glmsg.add_args();
-    arg_dstAlpha->set_isarray(false);
-    arg_dstAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_dstAlpha->add_intvalue((int)dstAlpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendFuncSeparateiEXT(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColorMaskiEXT(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColorMaskiEXT);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::BOOL);
-    arg_r->add_boolvalue(r);
-
-    // copy argument g
-    GLMessage_DataType *arg_g = glmsg.add_args();
-    arg_g->set_isarray(false);
-    arg_g->set_type(GLMessage::DataType::BOOL);
-    arg_g->add_boolvalue(g);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::BOOL);
-    arg_b->add_boolvalue(b);
-
-    // copy argument a
-    GLMessage_DataType *arg_a = glmsg.add_args();
-    arg_a->set_isarray(false);
-    arg_a->set_type(GLMessage::DataType::BOOL);
-    arg_a->add_boolvalue(a);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColorMaskiEXT(index, r, g, b, a);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsEnablediEXT(GLenum target, GLuint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsEnablediEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsEnablediEXT(target, index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glDrawArraysInstancedEXT(GLenum mode, GLint start, GLsizei count, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawArraysInstancedEXT);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument start
-    GLMessage_DataType *arg_start = glmsg.add_args();
-    arg_start->set_isarray(false);
-    arg_start->set_type(GLMessage::DataType::INT);
-    arg_start->add_intvalue(start);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawArraysInstancedEXT(mode, start, count, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawElementsInstancedEXT);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawElementsInstancedEXT(mode, count, type, indices, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTextureEXT(GLenum target, GLenum attachment, GLuint texture, GLint level) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTextureEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTextureEXT(target, attachment, texture, level);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribDivisorEXT(GLuint index, GLuint divisor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribDivisorEXT);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument divisor
-    GLMessage_DataType *arg_divisor = glmsg.add_args();
-    arg_divisor->set_isarray(false);
-    arg_divisor->set_type(GLMessage::DataType::INT);
-    arg_divisor->add_intvalue(divisor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribDivisorEXT(index, divisor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void * GLTrace_glMapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMapBufferRangeEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // copy argument access
-    GLMessage_DataType *arg_access = glmsg.add_args();
-    arg_access->set_isarray(false);
-    arg_access->set_type(GLMessage::DataType::INT);
-    arg_access->add_intvalue(access);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    void * retValue = glContext->hooks->gl.glMapBufferRangeEXT(target, offset, length, access);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT64);
-    rt->add_int64value((uintptr_t)retValue);
-
-    void *pointerArgs[] = {
-        (void *) retValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glFlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFlushMappedBufferRangeEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT);
-    arg_length->add_intvalue(length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFlushMappedBufferRangeEXT(target, offset, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiDrawArraysEXT(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiDrawArraysEXT);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument first
-    GLMessage_DataType *arg_first = glmsg.add_args();
-    arg_first->set_isarray(false);
-    arg_first->set_type(GLMessage::DataType::INT64);
-    arg_first->add_int64value((uintptr_t)first);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT64);
-    arg_count->add_int64value((uintptr_t)count);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiDrawArraysEXT(mode, first, count, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) first,
-        (void *) count,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiDrawElementsEXT);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT64);
-    arg_count->add_int64value((uintptr_t)count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiDrawElementsEXT(mode, count, type, indices, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) count,
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageMultisampleEXT(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageMultisampleEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTexture2DMultisampleEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument textarget
-    GLMessage_DataType *arg_textarget = glmsg.add_args();
-    arg_textarget->set_isarray(false);
-    arg_textarget->set_type(GLMessage::DataType::ENUM);
-    arg_textarget->add_intvalue((int)textarget);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTexture2DMultisampleEXT(target, attachment, textarget, texture, level, samples);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glReadBufferIndexedEXT(GLenum src, GLint index) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glReadBufferIndexedEXT);
-
-    // copy argument src
-    GLMessage_DataType *arg_src = glmsg.add_args();
-    arg_src->set_isarray(false);
-    arg_src->set_type(GLMessage::DataType::ENUM);
-    arg_src->add_intvalue((int)src);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glReadBufferIndexedEXT(src, index);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawBuffersIndexedEXT(GLint n, const GLenum * location, const GLint * indices) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawBuffersIndexedEXT);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT64);
-    arg_location->add_int64value((uintptr_t)location);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawBuffersIndexedEXT(n, location, indices);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) location,
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetIntegeri_vEXT(GLenum target, GLuint index, GLint * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetIntegeri_vEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetIntegeri_vEXT(target, index, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPrimitiveBoundingBoxEXT(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPrimitiveBoundingBoxEXT);
-
-    // copy argument minX
-    GLMessage_DataType *arg_minX = glmsg.add_args();
-    arg_minX->set_isarray(false);
-    arg_minX->set_type(GLMessage::DataType::FLOAT);
-    arg_minX->add_floatvalue(minX);
-
-    // copy argument minY
-    GLMessage_DataType *arg_minY = glmsg.add_args();
-    arg_minY->set_isarray(false);
-    arg_minY->set_type(GLMessage::DataType::FLOAT);
-    arg_minY->add_floatvalue(minY);
-
-    // copy argument minZ
-    GLMessage_DataType *arg_minZ = glmsg.add_args();
-    arg_minZ->set_isarray(false);
-    arg_minZ->set_type(GLMessage::DataType::FLOAT);
-    arg_minZ->add_floatvalue(minZ);
-
-    // copy argument minW
-    GLMessage_DataType *arg_minW = glmsg.add_args();
-    arg_minW->set_isarray(false);
-    arg_minW->set_type(GLMessage::DataType::FLOAT);
-    arg_minW->add_floatvalue(minW);
-
-    // copy argument maxX
-    GLMessage_DataType *arg_maxX = glmsg.add_args();
-    arg_maxX->set_isarray(false);
-    arg_maxX->set_type(GLMessage::DataType::FLOAT);
-    arg_maxX->add_floatvalue(maxX);
-
-    // copy argument maxY
-    GLMessage_DataType *arg_maxY = glmsg.add_args();
-    arg_maxY->set_isarray(false);
-    arg_maxY->set_type(GLMessage::DataType::FLOAT);
-    arg_maxY->add_floatvalue(maxY);
-
-    // copy argument maxZ
-    GLMessage_DataType *arg_maxZ = glmsg.add_args();
-    arg_maxZ->set_isarray(false);
-    arg_maxZ->set_type(GLMessage::DataType::FLOAT);
-    arg_maxZ->add_floatvalue(maxZ);
-
-    // copy argument maxW
-    GLMessage_DataType *arg_maxW = glmsg.add_args();
-    arg_maxW->set_isarray(false);
-    arg_maxW->set_type(GLMessage::DataType::FLOAT);
-    arg_maxW->add_floatvalue(maxW);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPrimitiveBoundingBoxEXT(minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLenum GLTrace_glGetGraphicsResetStatusEXT(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetGraphicsResetStatusEXT);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLenum retValue = glContext->hooks->gl.glGetGraphicsResetStatusEXT();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::ENUM);
-    rt->add_intvalue((int)retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glReadnPixelsEXT);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glReadnPixelsEXT(x, y, width, height, format, type, bufSize, data);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetnUniformfvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetnUniformfvEXT(program, location, bufSize, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetnUniformivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetnUniformivEXT(program, location, bufSize, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glActiveShaderProgramEXT(GLuint pipeline, GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glActiveShaderProgramEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glActiveShaderProgramEXT(pipeline, program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBindProgramPipelineEXT(GLuint pipeline) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindProgramPipelineEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindProgramPipelineEXT(pipeline);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLuint GLTrace_glCreateShaderProgramvEXT(GLenum type, GLsizei count, const GLchar ** strings) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCreateShaderProgramvEXT);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument strings
-    GLMessage_DataType *arg_strings = glmsg.add_args();
-    arg_strings->set_isarray(false);
-    arg_strings->set_type(GLMessage::DataType::INT64);
-    arg_strings->add_int64value((uintptr_t)strings);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLuint retValue = glContext->hooks->gl.glCreateShaderProgramvEXT(type, count, strings);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) strings,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glDeleteProgramPipelinesEXT(GLsizei n, const GLuint * pipelines) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteProgramPipelinesEXT);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument pipelines
-    GLMessage_DataType *arg_pipelines = glmsg.add_args();
-    arg_pipelines->set_isarray(false);
-    arg_pipelines->set_type(GLMessage::DataType::INT64);
-    arg_pipelines->add_int64value((uintptr_t)pipelines);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteProgramPipelinesEXT(n, pipelines);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pipelines,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenProgramPipelinesEXT(GLsizei n, GLuint * pipelines) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenProgramPipelinesEXT);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument pipelines
-    GLMessage_DataType *arg_pipelines = glmsg.add_args();
-    arg_pipelines->set_isarray(false);
-    arg_pipelines->set_type(GLMessage::DataType::INT64);
-    arg_pipelines->add_int64value((uintptr_t)pipelines);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenProgramPipelinesEXT(n, pipelines);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pipelines,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramPipelineInfoLogEXT(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramPipelineInfoLogEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument infoLog
-    GLMessage_DataType *arg_infoLog = glmsg.add_args();
-    arg_infoLog->set_isarray(false);
-    arg_infoLog->set_type(GLMessage::DataType::INT64);
-    arg_infoLog->add_int64value((uintptr_t)infoLog);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramPipelineInfoLogEXT(pipeline, bufSize, length, infoLog);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) infoLog,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetProgramPipelineivEXT(GLuint pipeline, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetProgramPipelineivEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetProgramPipelineivEXT(pipeline, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsProgramPipelineEXT(GLuint pipeline) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsProgramPipelineEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsProgramPipelineEXT(pipeline);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glProgramParameteriEXT(GLuint program, GLenum pname, GLint value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramParameteriEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramParameteriEXT(program, pname, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1fEXT(GLuint program, GLint location, GLfloat v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1fEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1fEXT(program, location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1fvEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1iEXT(GLuint program, GLint location, GLint v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1iEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1iEXT(program, location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1ivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1ivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2fEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2fEXT(program, location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2fvEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2iEXT(GLuint program, GLint location, GLint v0, GLint v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2iEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2iEXT(program, location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2ivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2ivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3fEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::FLOAT);
-    arg_v2->add_floatvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3fEXT(program, location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3fvEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3iEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3iEXT(program, location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3ivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3ivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4fEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::FLOAT);
-    arg_v0->add_floatvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::FLOAT);
-    arg_v1->add_floatvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::FLOAT);
-    arg_v2->add_floatvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::FLOAT);
-    arg_v3->add_floatvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4fEXT(program, location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4fvEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4iEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::INT);
-    arg_v3->add_intvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4iEXT(program, location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4ivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4ivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix2fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix2fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix3fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix3fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix4fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix4fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUseProgramStagesEXT(GLuint pipeline, GLbitfield stages, GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUseProgramStagesEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // copy argument stages
-    GLMessage_DataType *arg_stages = glmsg.add_args();
-    arg_stages->set_isarray(false);
-    arg_stages->set_type(GLMessage::DataType::INT);
-    arg_stages->add_intvalue(stages);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUseProgramStagesEXT(pipeline, stages, program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glValidateProgramPipelineEXT(GLuint pipeline) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glValidateProgramPipelineEXT);
-
-    // copy argument pipeline
-    GLMessage_DataType *arg_pipeline = glmsg.add_args();
-    arg_pipeline->set_isarray(false);
-    arg_pipeline->set_type(GLMessage::DataType::INT);
-    arg_pipeline->add_intvalue(pipeline);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glValidateProgramPipelineEXT(pipeline);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1uiEXT(GLuint program, GLint location, GLuint v0) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1uiEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1uiEXT(program, location, v0);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2uiEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2uiEXT(program, location, v0, v1);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3uiEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3uiEXT(program, location, v0, v1, v2);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4uiEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument v0
-    GLMessage_DataType *arg_v0 = glmsg.add_args();
-    arg_v0->set_isarray(false);
-    arg_v0->set_type(GLMessage::DataType::INT);
-    arg_v0->add_intvalue(v0);
-
-    // copy argument v1
-    GLMessage_DataType *arg_v1 = glmsg.add_args();
-    arg_v1->set_isarray(false);
-    arg_v1->set_type(GLMessage::DataType::INT);
-    arg_v1->add_intvalue(v1);
-
-    // copy argument v2
-    GLMessage_DataType *arg_v2 = glmsg.add_args();
-    arg_v2->set_isarray(false);
-    arg_v2->set_type(GLMessage::DataType::INT);
-    arg_v2->add_intvalue(v2);
-
-    // copy argument v3
-    GLMessage_DataType *arg_v3 = glmsg.add_args();
-    arg_v3->set_isarray(false);
-    arg_v3->set_type(GLMessage::DataType::INT);
-    arg_v3->add_intvalue(v3);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4uiEXT(program, location, v0, v1, v2, v3);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform1uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform1uivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform1uivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform2uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform2uivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform2uivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform3uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform3uivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform3uivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniform4uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniform4uivEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniform4uivEXT(program, location, count, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix2x3fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix2x3fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix3x2fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix3x2fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix2x4fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix2x4fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix4x2fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix4x2fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix3x4fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix3x4fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glProgramUniformMatrix4x3fvEXT);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glProgramUniformMatrix4x3fvEXT(program, location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPatchParameteriEXT(GLenum pname, GLint value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPatchParameteriEXT);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPatchParameteriEXT(pname, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterIivEXT(GLenum target, GLenum pname, const GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterIivEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterIivEXT(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterIuivEXT(GLenum target, GLenum pname, const GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterIuivEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterIuivEXT(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexParameterIivEXT(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexParameterIivEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexParameterIivEXT(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexParameterIuivEXT(GLenum target, GLenum pname, GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexParameterIuivEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexParameterIuivEXT(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSamplerParameterIivEXT(GLuint sampler, GLenum pname, const GLint * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSamplerParameterIivEXT);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSamplerParameterIivEXT(sampler, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSamplerParameterIuivEXT(GLuint sampler, GLenum pname, const GLuint * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSamplerParameterIuivEXT);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSamplerParameterIuivEXT(sampler, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetSamplerParameterIivEXT(GLuint sampler, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetSamplerParameterIivEXT);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetSamplerParameterIivEXT(sampler, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetSamplerParameterIuivEXT(GLuint sampler, GLenum pname, GLuint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetSamplerParameterIuivEXT);
-
-    // copy argument sampler
-    GLMessage_DataType *arg_sampler = glmsg.add_args();
-    arg_sampler->set_isarray(false);
-    arg_sampler->set_type(GLMessage::DataType::INT);
-    arg_sampler->add_intvalue(sampler);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetSamplerParameterIuivEXT(sampler, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexBufferEXT(GLenum target, GLenum internalformat, GLuint buffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexBufferEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexBufferEXT(target, internalformat, buffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexBufferRangeEXT(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexBufferRangeEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument buffer
-    GLMessage_DataType *arg_buffer = glmsg.add_args();
-    arg_buffer->set_isarray(false);
-    arg_buffer->set_type(GLMessage::DataType::INT);
-    arg_buffer->add_intvalue(buffer);
-
-    // copy argument offset
-    GLMessage_DataType *arg_offset = glmsg.add_args();
-    arg_offset->set_isarray(false);
-    arg_offset->set_type(GLMessage::DataType::INT);
-    arg_offset->add_intvalue(offset);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexBufferRangeEXT(target, internalformat, buffer, offset, size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage1DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage1DEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage1DEXT(target, levels, internalformat, width);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage2DEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage2DEXT(target, levels, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexStorage3DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexStorage3DEXT);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexStorage3DEXT(target, levels, internalformat, width, height, depth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTextureStorage1DEXT);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTextureStorage1DEXT(texture, target, levels, internalformat, width);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTextureStorage2DEXT);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTextureStorage2DEXT(texture, target, levels, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTextureStorage3DEXT);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument levels
-    GLMessage_DataType *arg_levels = glmsg.add_args();
-    arg_levels->set_isarray(false);
-    arg_levels->set_type(GLMessage::DataType::INT);
-    arg_levels->add_intvalue(levels);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTextureStorage3DEXT(texture, target, levels, internalformat, width, height, depth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTextureViewEXT(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTextureViewEXT);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument origtexture
-    GLMessage_DataType *arg_origtexture = glmsg.add_args();
-    arg_origtexture->set_isarray(false);
-    arg_origtexture->set_type(GLMessage::DataType::INT);
-    arg_origtexture->add_intvalue(origtexture);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument minlevel
-    GLMessage_DataType *arg_minlevel = glmsg.add_args();
-    arg_minlevel->set_isarray(false);
-    arg_minlevel->set_type(GLMessage::DataType::INT);
-    arg_minlevel->add_intvalue(minlevel);
-
-    // copy argument numlevels
-    GLMessage_DataType *arg_numlevels = glmsg.add_args();
-    arg_numlevels->set_isarray(false);
-    arg_numlevels->set_type(GLMessage::DataType::INT);
-    arg_numlevels->add_intvalue(numlevels);
-
-    // copy argument minlayer
-    GLMessage_DataType *arg_minlayer = glmsg.add_args();
-    arg_minlayer->set_isarray(false);
-    arg_minlayer->set_type(GLMessage::DataType::INT);
-    arg_minlayer->add_intvalue(minlayer);
-
-    // copy argument numlayers
-    GLMessage_DataType *arg_numlayers = glmsg.add_args();
-    arg_numlayers->set_isarray(false);
-    arg_numlayers->set_type(GLMessage::DataType::INT);
-    arg_numlayers->add_intvalue(numlayers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTextureViewEXT(texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageMultisampleIMG(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageMultisampleIMG);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageMultisampleIMG(target, samples, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTexture2DMultisampleIMG(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTexture2DMultisampleIMG);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument textarget
-    GLMessage_DataType *arg_textarget = glmsg.add_args();
-    arg_textarget->set_isarray(false);
-    arg_textarget->set_type(GLMessage::DataType::ENUM);
-    arg_textarget->add_intvalue((int)textarget);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTexture2DMultisampleIMG(target, attachment, textarget, texture, level, samples);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBeginPerfQueryINTEL(GLuint queryHandle) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBeginPerfQueryINTEL);
-
-    // copy argument queryHandle
-    GLMessage_DataType *arg_queryHandle = glmsg.add_args();
-    arg_queryHandle->set_isarray(false);
-    arg_queryHandle->set_type(GLMessage::DataType::INT);
-    arg_queryHandle->add_intvalue(queryHandle);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBeginPerfQueryINTEL(queryHandle);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCreatePerfQueryINTEL(GLuint queryId, GLuint * queryHandle) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCreatePerfQueryINTEL);
-
-    // copy argument queryId
-    GLMessage_DataType *arg_queryId = glmsg.add_args();
-    arg_queryId->set_isarray(false);
-    arg_queryId->set_type(GLMessage::DataType::INT);
-    arg_queryId->add_intvalue(queryId);
-
-    // copy argument queryHandle
-    GLMessage_DataType *arg_queryHandle = glmsg.add_args();
-    arg_queryHandle->set_isarray(false);
-    arg_queryHandle->set_type(GLMessage::DataType::INT64);
-    arg_queryHandle->add_int64value((uintptr_t)queryHandle);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCreatePerfQueryINTEL(queryId, queryHandle);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) queryHandle,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeletePerfQueryINTEL(GLuint queryHandle) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeletePerfQueryINTEL);
-
-    // copy argument queryHandle
-    GLMessage_DataType *arg_queryHandle = glmsg.add_args();
-    arg_queryHandle->set_isarray(false);
-    arg_queryHandle->set_type(GLMessage::DataType::INT);
-    arg_queryHandle->add_intvalue(queryHandle);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeletePerfQueryINTEL(queryHandle);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEndPerfQueryINTEL(GLuint queryHandle) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEndPerfQueryINTEL);
-
-    // copy argument queryHandle
-    GLMessage_DataType *arg_queryHandle = glmsg.add_args();
-    arg_queryHandle->set_isarray(false);
-    arg_queryHandle->set_type(GLMessage::DataType::INT);
-    arg_queryHandle->add_intvalue(queryHandle);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEndPerfQueryINTEL(queryHandle);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetFirstPerfQueryIdINTEL(GLuint * queryId) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFirstPerfQueryIdINTEL);
-
-    // copy argument queryId
-    GLMessage_DataType *arg_queryId = glmsg.add_args();
-    arg_queryId->set_isarray(false);
-    arg_queryId->set_type(GLMessage::DataType::INT64);
-    arg_queryId->add_int64value((uintptr_t)queryId);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFirstPerfQueryIdINTEL(queryId);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) queryId,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetNextPerfQueryIdINTEL(GLuint queryId, GLuint * nextQueryId) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetNextPerfQueryIdINTEL);
-
-    // copy argument queryId
-    GLMessage_DataType *arg_queryId = glmsg.add_args();
-    arg_queryId->set_isarray(false);
-    arg_queryId->set_type(GLMessage::DataType::INT);
-    arg_queryId->add_intvalue(queryId);
-
-    // copy argument nextQueryId
-    GLMessage_DataType *arg_nextQueryId = glmsg.add_args();
-    arg_nextQueryId->set_isarray(false);
-    arg_nextQueryId->set_type(GLMessage::DataType::INT64);
-    arg_nextQueryId->add_int64value((uintptr_t)nextQueryId);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetNextPerfQueryIdINTEL(queryId, nextQueryId);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) nextQueryId,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfCounterInfoINTEL(GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar * counterName, GLuint counterDescLength, GLchar * counterDesc, GLuint * counterOffset, GLuint * counterDataSize, GLuint * counterTypeEnum, GLuint * counterDataTypeEnum, GLuint64 * rawCounterMaxValue) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfCounterInfoINTEL);
-
-    // copy argument queryId
-    GLMessage_DataType *arg_queryId = glmsg.add_args();
-    arg_queryId->set_isarray(false);
-    arg_queryId->set_type(GLMessage::DataType::INT);
-    arg_queryId->add_intvalue(queryId);
-
-    // copy argument counterId
-    GLMessage_DataType *arg_counterId = glmsg.add_args();
-    arg_counterId->set_isarray(false);
-    arg_counterId->set_type(GLMessage::DataType::INT);
-    arg_counterId->add_intvalue(counterId);
-
-    // copy argument counterNameLength
-    GLMessage_DataType *arg_counterNameLength = glmsg.add_args();
-    arg_counterNameLength->set_isarray(false);
-    arg_counterNameLength->set_type(GLMessage::DataType::INT);
-    arg_counterNameLength->add_intvalue(counterNameLength);
-
-    // copy argument counterName
-    GLMessage_DataType *arg_counterName = glmsg.add_args();
-    arg_counterName->set_isarray(false);
-    arg_counterName->set_type(GLMessage::DataType::INT64);
-    arg_counterName->add_int64value((uintptr_t)counterName);
-
-    // copy argument counterDescLength
-    GLMessage_DataType *arg_counterDescLength = glmsg.add_args();
-    arg_counterDescLength->set_isarray(false);
-    arg_counterDescLength->set_type(GLMessage::DataType::INT);
-    arg_counterDescLength->add_intvalue(counterDescLength);
-
-    // copy argument counterDesc
-    GLMessage_DataType *arg_counterDesc = glmsg.add_args();
-    arg_counterDesc->set_isarray(false);
-    arg_counterDesc->set_type(GLMessage::DataType::INT64);
-    arg_counterDesc->add_int64value((uintptr_t)counterDesc);
-
-    // copy argument counterOffset
-    GLMessage_DataType *arg_counterOffset = glmsg.add_args();
-    arg_counterOffset->set_isarray(false);
-    arg_counterOffset->set_type(GLMessage::DataType::INT64);
-    arg_counterOffset->add_int64value((uintptr_t)counterOffset);
-
-    // copy argument counterDataSize
-    GLMessage_DataType *arg_counterDataSize = glmsg.add_args();
-    arg_counterDataSize->set_isarray(false);
-    arg_counterDataSize->set_type(GLMessage::DataType::INT64);
-    arg_counterDataSize->add_int64value((uintptr_t)counterDataSize);
-
-    // copy argument counterTypeEnum
-    GLMessage_DataType *arg_counterTypeEnum = glmsg.add_args();
-    arg_counterTypeEnum->set_isarray(false);
-    arg_counterTypeEnum->set_type(GLMessage::DataType::INT64);
-    arg_counterTypeEnum->add_int64value((uintptr_t)counterTypeEnum);
-
-    // copy argument counterDataTypeEnum
-    GLMessage_DataType *arg_counterDataTypeEnum = glmsg.add_args();
-    arg_counterDataTypeEnum->set_isarray(false);
-    arg_counterDataTypeEnum->set_type(GLMessage::DataType::INT64);
-    arg_counterDataTypeEnum->add_int64value((uintptr_t)counterDataTypeEnum);
-
-    // copy argument rawCounterMaxValue
-    GLMessage_DataType *arg_rawCounterMaxValue = glmsg.add_args();
-    arg_rawCounterMaxValue->set_isarray(false);
-    arg_rawCounterMaxValue->set_type(GLMessage::DataType::INT64);
-    arg_rawCounterMaxValue->add_int64value((uintptr_t)rawCounterMaxValue);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfCounterInfoINTEL(queryId, counterId, counterNameLength, counterName, counterDescLength, counterDesc, counterOffset, counterDataSize, counterTypeEnum, counterDataTypeEnum, rawCounterMaxValue);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) counterName,
-        (void *) counterDesc,
-        (void *) counterOffset,
-        (void *) counterDataSize,
-        (void *) counterTypeEnum,
-        (void *) counterDataTypeEnum,
-        (void *) rawCounterMaxValue,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid * data, GLuint * bytesWritten) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfQueryDataINTEL);
-
-    // copy argument queryHandle
-    GLMessage_DataType *arg_queryHandle = glmsg.add_args();
-    arg_queryHandle->set_isarray(false);
-    arg_queryHandle->set_type(GLMessage::DataType::INT);
-    arg_queryHandle->add_intvalue(queryHandle);
-
-    // copy argument flags
-    GLMessage_DataType *arg_flags = glmsg.add_args();
-    arg_flags->set_isarray(false);
-    arg_flags->set_type(GLMessage::DataType::INT);
-    arg_flags->add_intvalue(flags);
-
-    // copy argument dataSize
-    GLMessage_DataType *arg_dataSize = glmsg.add_args();
-    arg_dataSize->set_isarray(false);
-    arg_dataSize->set_type(GLMessage::DataType::INT);
-    arg_dataSize->add_intvalue(dataSize);
-
-    // copy argument data
-    GLMessage_DataType *arg_data = glmsg.add_args();
-    arg_data->set_isarray(false);
-    arg_data->set_type(GLMessage::DataType::INT64);
-    arg_data->add_int64value((uintptr_t)data);
-
-    // copy argument bytesWritten
-    GLMessage_DataType *arg_bytesWritten = glmsg.add_args();
-    arg_bytesWritten->set_isarray(false);
-    arg_bytesWritten->set_type(GLMessage::DataType::INT64);
-    arg_bytesWritten->add_int64value((uintptr_t)bytesWritten);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfQueryDataINTEL(queryHandle, flags, dataSize, data, bytesWritten);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) data,
-        (void *) bytesWritten,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfQueryIdByNameINTEL(GLchar * queryName, GLuint * queryId) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfQueryIdByNameINTEL);
-
-    // copy argument queryName
-    GLMessage_DataType *arg_queryName = glmsg.add_args();
-    arg_queryName->set_isarray(false);
-    arg_queryName->set_type(GLMessage::DataType::INT64);
-    arg_queryName->add_int64value((uintptr_t)queryName);
-
-    // copy argument queryId
-    GLMessage_DataType *arg_queryId = glmsg.add_args();
-    arg_queryId->set_isarray(false);
-    arg_queryId->set_type(GLMessage::DataType::INT64);
-    arg_queryId->add_int64value((uintptr_t)queryId);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfQueryIdByNameINTEL(queryName, queryId);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) queryName,
-        (void *) queryId,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPerfQueryInfoINTEL(GLuint queryId, GLuint queryNameLength, GLchar * queryName, GLuint * dataSize, GLuint * noCounters, GLuint * noInstances, GLuint * capsMask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPerfQueryInfoINTEL);
-
-    // copy argument queryId
-    GLMessage_DataType *arg_queryId = glmsg.add_args();
-    arg_queryId->set_isarray(false);
-    arg_queryId->set_type(GLMessage::DataType::INT);
-    arg_queryId->add_intvalue(queryId);
-
-    // copy argument queryNameLength
-    GLMessage_DataType *arg_queryNameLength = glmsg.add_args();
-    arg_queryNameLength->set_isarray(false);
-    arg_queryNameLength->set_type(GLMessage::DataType::INT);
-    arg_queryNameLength->add_intvalue(queryNameLength);
-
-    // copy argument queryName
-    GLMessage_DataType *arg_queryName = glmsg.add_args();
-    arg_queryName->set_isarray(false);
-    arg_queryName->set_type(GLMessage::DataType::INT64);
-    arg_queryName->add_int64value((uintptr_t)queryName);
-
-    // copy argument dataSize
-    GLMessage_DataType *arg_dataSize = glmsg.add_args();
-    arg_dataSize->set_isarray(false);
-    arg_dataSize->set_type(GLMessage::DataType::INT64);
-    arg_dataSize->add_int64value((uintptr_t)dataSize);
-
-    // copy argument noCounters
-    GLMessage_DataType *arg_noCounters = glmsg.add_args();
-    arg_noCounters->set_isarray(false);
-    arg_noCounters->set_type(GLMessage::DataType::INT64);
-    arg_noCounters->add_int64value((uintptr_t)noCounters);
-
-    // copy argument noInstances
-    GLMessage_DataType *arg_noInstances = glmsg.add_args();
-    arg_noInstances->set_isarray(false);
-    arg_noInstances->set_type(GLMessage::DataType::INT64);
-    arg_noInstances->add_int64value((uintptr_t)noInstances);
-
-    // copy argument capsMask
-    GLMessage_DataType *arg_capsMask = glmsg.add_args();
-    arg_capsMask->set_isarray(false);
-    arg_capsMask->set_type(GLMessage::DataType::INT64);
-    arg_capsMask->add_int64value((uintptr_t)capsMask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPerfQueryInfoINTEL(queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, capsMask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) queryName,
-        (void *) dataSize,
-        (void *) noCounters,
-        (void *) noInstances,
-        (void *) capsMask,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendParameteriNV(GLenum pname, GLint value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendParameteriNV);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendParameteriNV(pname, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendBarrierNV(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendBarrierNV);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendBarrierNV();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCopyBufferSubDataNV(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCopyBufferSubDataNV);
-
-    // copy argument readTarget
-    GLMessage_DataType *arg_readTarget = glmsg.add_args();
-    arg_readTarget->set_isarray(false);
-    arg_readTarget->set_type(GLMessage::DataType::ENUM);
-    arg_readTarget->add_intvalue((int)readTarget);
-
-    // copy argument writeTarget
-    GLMessage_DataType *arg_writeTarget = glmsg.add_args();
-    arg_writeTarget->set_isarray(false);
-    arg_writeTarget->set_type(GLMessage::DataType::ENUM);
-    arg_writeTarget->add_intvalue((int)writeTarget);
-
-    // copy argument readOffset
-    GLMessage_DataType *arg_readOffset = glmsg.add_args();
-    arg_readOffset->set_isarray(false);
-    arg_readOffset->set_type(GLMessage::DataType::INT);
-    arg_readOffset->add_intvalue(readOffset);
-
-    // copy argument writeOffset
-    GLMessage_DataType *arg_writeOffset = glmsg.add_args();
-    arg_writeOffset->set_isarray(false);
-    arg_writeOffset->set_type(GLMessage::DataType::INT);
-    arg_writeOffset->add_intvalue(writeOffset);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCopyBufferSubDataNV(readTarget, writeTarget, readOffset, writeOffset, size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCoverageMaskNV(GLboolean mask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCoverageMaskNV);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::BOOL);
-    arg_mask->add_boolvalue(mask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCoverageMaskNV(mask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCoverageOperationNV(GLenum operation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCoverageOperationNV);
-
-    // copy argument operation
-    GLMessage_DataType *arg_operation = glmsg.add_args();
-    arg_operation->set_isarray(false);
-    arg_operation->set_type(GLMessage::DataType::ENUM);
-    arg_operation->add_intvalue((int)operation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCoverageOperationNV(operation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawBuffersNV(GLsizei n, const GLenum * bufs) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawBuffersNV);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument bufs
-    GLMessage_DataType *arg_bufs = glmsg.add_args();
-    arg_bufs->set_isarray(false);
-    arg_bufs->set_type(GLMessage::DataType::INT64);
-    arg_bufs->add_int64value((uintptr_t)bufs);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawBuffersNV(n, bufs);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) bufs,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawArraysInstancedNV(GLenum mode, GLint first, GLsizei count, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawArraysInstancedNV);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument first
-    GLMessage_DataType *arg_first = glmsg.add_args();
-    arg_first->set_isarray(false);
-    arg_first->set_type(GLMessage::DataType::INT);
-    arg_first->add_intvalue(first);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawArraysInstancedNV(mode, first, count, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawElementsInstancedNV(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawElementsInstancedNV);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument indices
-    GLMessage_DataType *arg_indices = glmsg.add_args();
-    arg_indices->set_isarray(false);
-    arg_indices->set_type(GLMessage::DataType::INT64);
-    arg_indices->add_int64value((uintptr_t)indices);
-
-    // copy argument primcount
-    GLMessage_DataType *arg_primcount = glmsg.add_args();
-    arg_primcount->set_isarray(false);
-    arg_primcount->set_type(GLMessage::DataType::INT);
-    arg_primcount->add_intvalue(primcount);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawElementsInstancedNV(mode, count, type, indices, primcount);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) indices,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteFencesNV(GLsizei n, const GLuint * fences) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteFencesNV);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument fences
-    GLMessage_DataType *arg_fences = glmsg.add_args();
-    arg_fences->set_isarray(false);
-    arg_fences->set_type(GLMessage::DataType::INT64);
-    arg_fences->add_int64value((uintptr_t)fences);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteFencesNV(n, fences);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) fences,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenFencesNV(GLsizei n, GLuint * fences) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenFencesNV);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument fences
-    GLMessage_DataType *arg_fences = glmsg.add_args();
-    arg_fences->set_isarray(false);
-    arg_fences->set_type(GLMessage::DataType::INT64);
-    arg_fences->add_int64value((uintptr_t)fences);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenFencesNV(n, fences);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) fences,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsFenceNV(GLuint fence) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsFenceNV);
-
-    // copy argument fence
-    GLMessage_DataType *arg_fence = glmsg.add_args();
-    arg_fence->set_isarray(false);
-    arg_fence->set_type(GLMessage::DataType::INT);
-    arg_fence->add_intvalue(fence);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsFenceNV(fence);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-GLboolean GLTrace_glTestFenceNV(GLuint fence) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTestFenceNV);
-
-    // copy argument fence
-    GLMessage_DataType *arg_fence = glmsg.add_args();
-    arg_fence->set_isarray(false);
-    arg_fence->set_type(GLMessage::DataType::INT);
-    arg_fence->add_intvalue(fence);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glTestFenceNV(fence);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glGetFenceivNV(GLuint fence, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFenceivNV);
-
-    // copy argument fence
-    GLMessage_DataType *arg_fence = glmsg.add_args();
-    arg_fence->set_isarray(false);
-    arg_fence->set_type(GLMessage::DataType::INT);
-    arg_fence->add_intvalue(fence);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFenceivNV(fence, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFinishFenceNV(GLuint fence) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFinishFenceNV);
-
-    // copy argument fence
-    GLMessage_DataType *arg_fence = glmsg.add_args();
-    arg_fence->set_isarray(false);
-    arg_fence->set_type(GLMessage::DataType::INT);
-    arg_fence->add_intvalue(fence);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFinishFenceNV(fence);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSetFenceNV(GLuint fence, GLenum condition) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSetFenceNV);
-
-    // copy argument fence
-    GLMessage_DataType *arg_fence = glmsg.add_args();
-    arg_fence->set_isarray(false);
-    arg_fence->set_type(GLMessage::DataType::INT);
-    arg_fence->add_intvalue(fence);
-
-    // copy argument condition
-    GLMessage_DataType *arg_condition = glmsg.add_args();
-    arg_condition->set_isarray(false);
-    arg_condition->set_type(GLMessage::DataType::ENUM);
-    arg_condition->add_intvalue((int)condition);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSetFenceNV(fence, condition);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlitFramebufferNV);
-
-    // copy argument srcX0
-    GLMessage_DataType *arg_srcX0 = glmsg.add_args();
-    arg_srcX0->set_isarray(false);
-    arg_srcX0->set_type(GLMessage::DataType::INT);
-    arg_srcX0->add_intvalue(srcX0);
-
-    // copy argument srcY0
-    GLMessage_DataType *arg_srcY0 = glmsg.add_args();
-    arg_srcY0->set_isarray(false);
-    arg_srcY0->set_type(GLMessage::DataType::INT);
-    arg_srcY0->add_intvalue(srcY0);
-
-    // copy argument srcX1
-    GLMessage_DataType *arg_srcX1 = glmsg.add_args();
-    arg_srcX1->set_isarray(false);
-    arg_srcX1->set_type(GLMessage::DataType::INT);
-    arg_srcX1->add_intvalue(srcX1);
-
-    // copy argument srcY1
-    GLMessage_DataType *arg_srcY1 = glmsg.add_args();
-    arg_srcY1->set_isarray(false);
-    arg_srcY1->set_type(GLMessage::DataType::INT);
-    arg_srcY1->add_intvalue(srcY1);
-
-    // copy argument dstX0
-    GLMessage_DataType *arg_dstX0 = glmsg.add_args();
-    arg_dstX0->set_isarray(false);
-    arg_dstX0->set_type(GLMessage::DataType::INT);
-    arg_dstX0->add_intvalue(dstX0);
-
-    // copy argument dstY0
-    GLMessage_DataType *arg_dstY0 = glmsg.add_args();
-    arg_dstY0->set_isarray(false);
-    arg_dstY0->set_type(GLMessage::DataType::INT);
-    arg_dstY0->add_intvalue(dstY0);
-
-    // copy argument dstX1
-    GLMessage_DataType *arg_dstX1 = glmsg.add_args();
-    arg_dstX1->set_isarray(false);
-    arg_dstX1->set_type(GLMessage::DataType::INT);
-    arg_dstX1->add_intvalue(dstX1);
-
-    // copy argument dstY1
-    GLMessage_DataType *arg_dstY1 = glmsg.add_args();
-    arg_dstY1->set_isarray(false);
-    arg_dstY1->set_type(GLMessage::DataType::INT);
-    arg_dstY1->add_intvalue(dstY1);
-
-    // copy argument mask
-    GLMessage_DataType *arg_mask = glmsg.add_args();
-    arg_mask->set_isarray(false);
-    arg_mask->set_type(GLMessage::DataType::INT);
-    arg_mask->add_intvalue(mask);
-
-    // copy argument filter
-    GLMessage_DataType *arg_filter = glmsg.add_args();
-    arg_filter->set_isarray(false);
-    arg_filter->set_type(GLMessage::DataType::ENUM);
-    arg_filter->add_intvalue((int)filter);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlitFramebufferNV(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageMultisampleNV(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageMultisampleNV);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument samples
-    GLMessage_DataType *arg_samples = glmsg.add_args();
-    arg_samples->set_isarray(false);
-    arg_samples->set_type(GLMessage::DataType::INT);
-    arg_samples->add_intvalue(samples);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageMultisampleNV(target, samples, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexAttribDivisorNV(GLuint index, GLuint divisor) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexAttribDivisorNV);
-
-    // copy argument index
-    GLMessage_DataType *arg_index = glmsg.add_args();
-    arg_index->set_isarray(false);
-    arg_index->set_type(GLMessage::DataType::INT);
-    arg_index->add_intvalue(index);
-
-    // copy argument divisor
-    GLMessage_DataType *arg_divisor = glmsg.add_args();
-    arg_divisor->set_isarray(false);
-    arg_divisor->set_type(GLMessage::DataType::INT);
-    arg_divisor->add_intvalue(divisor);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexAttribDivisorNV(index, divisor);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix2x3fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix2x3fvNV);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix2x3fvNV(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix3x2fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix3x2fvNV);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix3x2fvNV(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix2x4fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix2x4fvNV);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix2x4fvNV(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix4x2fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix4x2fvNV);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix4x2fvNV(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix3x4fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix3x4fvNV);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix3x4fvNV(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glUniformMatrix4x3fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glUniformMatrix4x3fvNV);
-
-    // copy argument location
-    GLMessage_DataType *arg_location = glmsg.add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-
-    // copy argument count
-    GLMessage_DataType *arg_count = glmsg.add_args();
-    arg_count->set_isarray(false);
-    arg_count->set_type(GLMessage::DataType::INT);
-    arg_count->add_intvalue(count);
-
-    // copy argument transpose
-    GLMessage_DataType *arg_transpose = glmsg.add_args();
-    arg_transpose->set_isarray(false);
-    arg_transpose->set_type(GLMessage::DataType::BOOL);
-    arg_transpose->add_boolvalue(transpose);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT64);
-    arg_value->add_int64value((uintptr_t)value);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glUniformMatrix4x3fvNV(location, count, transpose, value);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) value,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glReadBufferNV(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glReadBufferNV);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glReadBufferNV(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glAlphaFuncQCOM(GLenum func, GLclampf ref) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glAlphaFuncQCOM);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // copy argument ref
-    GLMessage_DataType *arg_ref = glmsg.add_args();
-    arg_ref->set_isarray(false);
-    arg_ref->set_type(GLMessage::DataType::FLOAT);
-    arg_ref->add_floatvalue(ref);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glAlphaFuncQCOM(func, ref);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetDriverControlsQCOM(GLint * num, GLsizei size, GLuint * driverControls) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetDriverControlsQCOM);
-
-    // copy argument num
-    GLMessage_DataType *arg_num = glmsg.add_args();
-    arg_num->set_isarray(false);
-    arg_num->set_type(GLMessage::DataType::INT64);
-    arg_num->add_int64value((uintptr_t)num);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument driverControls
-    GLMessage_DataType *arg_driverControls = glmsg.add_args();
-    arg_driverControls->set_isarray(false);
-    arg_driverControls->set_type(GLMessage::DataType::INT64);
-    arg_driverControls->add_int64value((uintptr_t)driverControls);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetDriverControlsQCOM(num, size, driverControls);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) num,
-        (void *) driverControls,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetDriverControlStringQCOM(GLuint driverControl, GLsizei bufSize, GLsizei * length, GLchar * driverControlString) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetDriverControlStringQCOM);
-
-    // copy argument driverControl
-    GLMessage_DataType *arg_driverControl = glmsg.add_args();
-    arg_driverControl->set_isarray(false);
-    arg_driverControl->set_type(GLMessage::DataType::INT);
-    arg_driverControl->add_intvalue(driverControl);
-
-    // copy argument bufSize
-    GLMessage_DataType *arg_bufSize = glmsg.add_args();
-    arg_bufSize->set_isarray(false);
-    arg_bufSize->set_type(GLMessage::DataType::INT);
-    arg_bufSize->add_intvalue(bufSize);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // copy argument driverControlString
-    GLMessage_DataType *arg_driverControlString = glmsg.add_args();
-    arg_driverControlString->set_isarray(false);
-    arg_driverControlString->set_type(GLMessage::DataType::INT64);
-    arg_driverControlString->add_int64value((uintptr_t)driverControlString);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetDriverControlStringQCOM(driverControl, bufSize, length, driverControlString);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) length,
-        (void *) driverControlString,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEnableDriverControlQCOM(GLuint driverControl) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEnableDriverControlQCOM);
-
-    // copy argument driverControl
-    GLMessage_DataType *arg_driverControl = glmsg.add_args();
-    arg_driverControl->set_isarray(false);
-    arg_driverControl->set_type(GLMessage::DataType::INT);
-    arg_driverControl->add_intvalue(driverControl);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEnableDriverControlQCOM(driverControl);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDisableDriverControlQCOM(GLuint driverControl) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDisableDriverControlQCOM);
-
-    // copy argument driverControl
-    GLMessage_DataType *arg_driverControl = glmsg.add_args();
-    arg_driverControl->set_isarray(false);
-    arg_driverControl->set_type(GLMessage::DataType::INT);
-    arg_driverControl->add_intvalue(driverControl);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDisableDriverControlQCOM(driverControl);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetTexturesQCOM(GLuint * textures, GLint maxTextures, GLint * numTextures) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetTexturesQCOM);
-
-    // copy argument textures
-    GLMessage_DataType *arg_textures = glmsg.add_args();
-    arg_textures->set_isarray(false);
-    arg_textures->set_type(GLMessage::DataType::INT64);
-    arg_textures->add_int64value((uintptr_t)textures);
-
-    // copy argument maxTextures
-    GLMessage_DataType *arg_maxTextures = glmsg.add_args();
-    arg_maxTextures->set_isarray(false);
-    arg_maxTextures->set_type(GLMessage::DataType::INT);
-    arg_maxTextures->add_intvalue(maxTextures);
-
-    // copy argument numTextures
-    GLMessage_DataType *arg_numTextures = glmsg.add_args();
-    arg_numTextures->set_isarray(false);
-    arg_numTextures->set_type(GLMessage::DataType::INT64);
-    arg_numTextures->add_int64value((uintptr_t)numTextures);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetTexturesQCOM(textures, maxTextures, numTextures);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) textures,
-        (void *) numTextures,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetBuffersQCOM(GLuint * buffers, GLint maxBuffers, GLint * numBuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetBuffersQCOM);
-
-    // copy argument buffers
-    GLMessage_DataType *arg_buffers = glmsg.add_args();
-    arg_buffers->set_isarray(false);
-    arg_buffers->set_type(GLMessage::DataType::INT64);
-    arg_buffers->add_int64value((uintptr_t)buffers);
-
-    // copy argument maxBuffers
-    GLMessage_DataType *arg_maxBuffers = glmsg.add_args();
-    arg_maxBuffers->set_isarray(false);
-    arg_maxBuffers->set_type(GLMessage::DataType::INT);
-    arg_maxBuffers->add_intvalue(maxBuffers);
-
-    // copy argument numBuffers
-    GLMessage_DataType *arg_numBuffers = glmsg.add_args();
-    arg_numBuffers->set_isarray(false);
-    arg_numBuffers->set_type(GLMessage::DataType::INT64);
-    arg_numBuffers->add_int64value((uintptr_t)numBuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetBuffersQCOM(buffers, maxBuffers, numBuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) buffers,
-        (void *) numBuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetRenderbuffersQCOM(GLuint * renderbuffers, GLint maxRenderbuffers, GLint * numRenderbuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetRenderbuffersQCOM);
-
-    // copy argument renderbuffers
-    GLMessage_DataType *arg_renderbuffers = glmsg.add_args();
-    arg_renderbuffers->set_isarray(false);
-    arg_renderbuffers->set_type(GLMessage::DataType::INT64);
-    arg_renderbuffers->add_int64value((uintptr_t)renderbuffers);
-
-    // copy argument maxRenderbuffers
-    GLMessage_DataType *arg_maxRenderbuffers = glmsg.add_args();
-    arg_maxRenderbuffers->set_isarray(false);
-    arg_maxRenderbuffers->set_type(GLMessage::DataType::INT);
-    arg_maxRenderbuffers->add_intvalue(maxRenderbuffers);
-
-    // copy argument numRenderbuffers
-    GLMessage_DataType *arg_numRenderbuffers = glmsg.add_args();
-    arg_numRenderbuffers->set_isarray(false);
-    arg_numRenderbuffers->set_type(GLMessage::DataType::INT64);
-    arg_numRenderbuffers->add_int64value((uintptr_t)numRenderbuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetRenderbuffersQCOM(renderbuffers, maxRenderbuffers, numRenderbuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) renderbuffers,
-        (void *) numRenderbuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetFramebuffersQCOM(GLuint * framebuffers, GLint maxFramebuffers, GLint * numFramebuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetFramebuffersQCOM);
-
-    // copy argument framebuffers
-    GLMessage_DataType *arg_framebuffers = glmsg.add_args();
-    arg_framebuffers->set_isarray(false);
-    arg_framebuffers->set_type(GLMessage::DataType::INT64);
-    arg_framebuffers->add_int64value((uintptr_t)framebuffers);
-
-    // copy argument maxFramebuffers
-    GLMessage_DataType *arg_maxFramebuffers = glmsg.add_args();
-    arg_maxFramebuffers->set_isarray(false);
-    arg_maxFramebuffers->set_type(GLMessage::DataType::INT);
-    arg_maxFramebuffers->add_intvalue(maxFramebuffers);
-
-    // copy argument numFramebuffers
-    GLMessage_DataType *arg_numFramebuffers = glmsg.add_args();
-    arg_numFramebuffers->set_isarray(false);
-    arg_numFramebuffers->set_type(GLMessage::DataType::INT64);
-    arg_numFramebuffers->add_int64value((uintptr_t)numFramebuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetFramebuffersQCOM(framebuffers, maxFramebuffers, numFramebuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) framebuffers,
-        (void *) numFramebuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetTexLevelParameterivQCOM(GLuint texture, GLenum face, GLint level, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetTexLevelParameterivQCOM);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetTexLevelParameterivQCOM(texture, face, level, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtTexObjectStateOverrideiQCOM(GLenum target, GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtTexObjectStateOverrideiQCOM);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtTexObjectStateOverrideiQCOM(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetTexSubImageQCOM(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void * texels) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetTexSubImageQCOM);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // copy argument xoffset
-    GLMessage_DataType *arg_xoffset = glmsg.add_args();
-    arg_xoffset->set_isarray(false);
-    arg_xoffset->set_type(GLMessage::DataType::INT);
-    arg_xoffset->add_intvalue(xoffset);
-
-    // copy argument yoffset
-    GLMessage_DataType *arg_yoffset = glmsg.add_args();
-    arg_yoffset->set_isarray(false);
-    arg_yoffset->set_type(GLMessage::DataType::INT);
-    arg_yoffset->add_intvalue(yoffset);
-
-    // copy argument zoffset
-    GLMessage_DataType *arg_zoffset = glmsg.add_args();
-    arg_zoffset->set_isarray(false);
-    arg_zoffset->set_type(GLMessage::DataType::INT);
-    arg_zoffset->add_intvalue(zoffset);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // copy argument format
-    GLMessage_DataType *arg_format = glmsg.add_args();
-    arg_format->set_isarray(false);
-    arg_format->set_type(GLMessage::DataType::ENUM);
-    arg_format->add_intvalue((int)format);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument texels
-    GLMessage_DataType *arg_texels = glmsg.add_args();
-    arg_texels->set_isarray(false);
-    arg_texels->set_type(GLMessage::DataType::INT64);
-    arg_texels->add_int64value((uintptr_t)texels);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetTexSubImageQCOM(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) texels,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetBufferPointervQCOM(GLenum target, void ** params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetBufferPointervQCOM);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetBufferPointervQCOM(target, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetShadersQCOM(GLuint * shaders, GLint maxShaders, GLint * numShaders) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetShadersQCOM);
-
-    // copy argument shaders
-    GLMessage_DataType *arg_shaders = glmsg.add_args();
-    arg_shaders->set_isarray(false);
-    arg_shaders->set_type(GLMessage::DataType::INT64);
-    arg_shaders->add_int64value((uintptr_t)shaders);
-
-    // copy argument maxShaders
-    GLMessage_DataType *arg_maxShaders = glmsg.add_args();
-    arg_maxShaders->set_isarray(false);
-    arg_maxShaders->set_type(GLMessage::DataType::INT);
-    arg_maxShaders->add_intvalue(maxShaders);
-
-    // copy argument numShaders
-    GLMessage_DataType *arg_numShaders = glmsg.add_args();
-    arg_numShaders->set_isarray(false);
-    arg_numShaders->set_type(GLMessage::DataType::INT64);
-    arg_numShaders->add_int64value((uintptr_t)numShaders);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetShadersQCOM(shaders, maxShaders, numShaders);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) shaders,
-        (void *) numShaders,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glExtGetProgramsQCOM(GLuint * programs, GLint maxPrograms, GLint * numPrograms) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetProgramsQCOM);
-
-    // copy argument programs
-    GLMessage_DataType *arg_programs = glmsg.add_args();
-    arg_programs->set_isarray(false);
-    arg_programs->set_type(GLMessage::DataType::INT64);
-    arg_programs->add_int64value((uintptr_t)programs);
-
-    // copy argument maxPrograms
-    GLMessage_DataType *arg_maxPrograms = glmsg.add_args();
-    arg_maxPrograms->set_isarray(false);
-    arg_maxPrograms->set_type(GLMessage::DataType::INT);
-    arg_maxPrograms->add_intvalue(maxPrograms);
-
-    // copy argument numPrograms
-    GLMessage_DataType *arg_numPrograms = glmsg.add_args();
-    arg_numPrograms->set_isarray(false);
-    arg_numPrograms->set_type(GLMessage::DataType::INT64);
-    arg_numPrograms->add_int64value((uintptr_t)numPrograms);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetProgramsQCOM(programs, maxPrograms, numPrograms);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) programs,
-        (void *) numPrograms,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glExtIsProgramBinaryQCOM(GLuint program) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtIsProgramBinaryQCOM);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glExtIsProgramBinaryQCOM(program);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glExtGetProgramBinarySourceQCOM(GLuint program, GLenum shadertype, GLchar * source, GLint * length) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glExtGetProgramBinarySourceQCOM);
-
-    // copy argument program
-    GLMessage_DataType *arg_program = glmsg.add_args();
-    arg_program->set_isarray(false);
-    arg_program->set_type(GLMessage::DataType::INT);
-    arg_program->add_intvalue(program);
-
-    // copy argument shadertype
-    GLMessage_DataType *arg_shadertype = glmsg.add_args();
-    arg_shadertype->set_isarray(false);
-    arg_shadertype->set_type(GLMessage::DataType::ENUM);
-    arg_shadertype->add_intvalue((int)shadertype);
-
-    // copy argument source
-    GLMessage_DataType *arg_source = glmsg.add_args();
-    arg_source->set_isarray(false);
-    arg_source->set_type(GLMessage::DataType::INT64);
-    arg_source->add_int64value((uintptr_t)source);
-
-    // copy argument length
-    GLMessage_DataType *arg_length = glmsg.add_args();
-    arg_length->set_isarray(false);
-    arg_length->set_type(GLMessage::DataType::INT64);
-    arg_length->add_int64value((uintptr_t)length);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glExtGetProgramBinarySourceQCOM(program, shadertype, source, length);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) source,
-        (void *) length,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glStartTilingQCOM(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glStartTilingQCOM);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // copy argument preserveMask
-    GLMessage_DataType *arg_preserveMask = glmsg.add_args();
-    arg_preserveMask->set_isarray(false);
-    arg_preserveMask->set_type(GLMessage::DataType::INT);
-    arg_preserveMask->add_intvalue(preserveMask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glStartTilingQCOM(x, y, width, height, preserveMask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEndTilingQCOM(GLbitfield preserveMask) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEndTilingQCOM);
-
-    // copy argument preserveMask
-    GLMessage_DataType *arg_preserveMask = glmsg.add_args();
-    arg_preserveMask->set_isarray(false);
-    arg_preserveMask->set_type(GLMessage::DataType::INT);
-    arg_preserveMask->add_intvalue(preserveMask);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEndTilingQCOM(preserveMask);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-
-// Definitions for GL1 APIs
-
-void GLTrace_glAlphaFunc(GLenum func, GLfloat ref) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glAlphaFunc);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // copy argument ref
-    GLMessage_DataType *arg_ref = glmsg.add_args();
-    arg_ref->set_isarray(false);
-    arg_ref->set_type(GLMessage::DataType::FLOAT);
-    arg_ref->add_floatvalue(ref);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glAlphaFunc(func, ref);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClipPlanef(GLenum p, const GLfloat * eqn) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClipPlanef);
-
-    // copy argument p
-    GLMessage_DataType *arg_p = glmsg.add_args();
-    arg_p->set_isarray(false);
-    arg_p->set_type(GLMessage::DataType::ENUM);
-    arg_p->add_intvalue((int)p);
-
-    // copy argument eqn
-    GLMessage_DataType *arg_eqn = glmsg.add_args();
-    arg_eqn->set_isarray(false);
-    arg_eqn->set_type(GLMessage::DataType::INT64);
-    arg_eqn->add_int64value((uintptr_t)eqn);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClipPlanef(p, eqn);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) eqn,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColor4f);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::FLOAT);
-    arg_red->add_floatvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::FLOAT);
-    arg_green->add_floatvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::FLOAT);
-    arg_blue->add_floatvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::FLOAT);
-    arg_alpha->add_floatvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColor4f(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFogf(GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFogf);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFogf(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFogfv(GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFogfv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFogfv(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFrustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFrustumf);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::FLOAT);
-    arg_l->add_floatvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::FLOAT);
-    arg_r->add_floatvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::FLOAT);
-    arg_b->add_floatvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::FLOAT);
-    arg_t->add_floatvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::FLOAT);
-    arg_n->add_floatvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::FLOAT);
-    arg_f->add_floatvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFrustumf(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetClipPlanef(GLenum plane, GLfloat * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetClipPlanef);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetClipPlanef(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetLightfv(GLenum light, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetLightfv);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetLightfv(light, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetMaterialfv(GLenum face, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetMaterialfv);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetMaterialfv(face, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexEnvfv(GLenum target, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexEnvfv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexEnvfv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightModelf(GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightModelf);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightModelf(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightModelfv(GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightModelfv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightModelfv(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightf(GLenum light, GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightf);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightf(light, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightfv(GLenum light, GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightfv);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightfv(light, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLoadMatrixf(const GLfloat * m) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLoadMatrixf);
-
-    // copy argument m
-    GLMessage_DataType *arg_m = glmsg.add_args();
-    arg_m->set_isarray(false);
-    arg_m->set_type(GLMessage::DataType::INT64);
-    arg_m->add_int64value((uintptr_t)m);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLoadMatrixf(m);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) m,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMaterialf(GLenum face, GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMaterialf);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMaterialf(face, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMaterialfv(GLenum face, GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMaterialfv);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMaterialfv(face, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultMatrixf(const GLfloat * m) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultMatrixf);
-
-    // copy argument m
-    GLMessage_DataType *arg_m = glmsg.add_args();
-    arg_m->set_isarray(false);
-    arg_m->set_type(GLMessage::DataType::INT64);
-    arg_m->add_int64value((uintptr_t)m);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultMatrixf(m);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) m,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord4f);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::FLOAT);
-    arg_s->add_floatvalue(s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::FLOAT);
-    arg_t->add_floatvalue(t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::FLOAT);
-    arg_r->add_floatvalue(r);
-
-    // copy argument q
-    GLMessage_DataType *arg_q = glmsg.add_args();
-    arg_q->set_isarray(false);
-    arg_q->set_type(GLMessage::DataType::FLOAT);
-    arg_q->add_floatvalue(q);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord4f(target, s, t, r, q);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glNormal3f);
-
-    // copy argument nx
-    GLMessage_DataType *arg_nx = glmsg.add_args();
-    arg_nx->set_isarray(false);
-    arg_nx->set_type(GLMessage::DataType::FLOAT);
-    arg_nx->add_floatvalue(nx);
-
-    // copy argument ny
-    GLMessage_DataType *arg_ny = glmsg.add_args();
-    arg_ny->set_isarray(false);
-    arg_ny->set_type(GLMessage::DataType::FLOAT);
-    arg_ny->add_floatvalue(ny);
-
-    // copy argument nz
-    GLMessage_DataType *arg_nz = glmsg.add_args();
-    arg_nz->set_isarray(false);
-    arg_nz->set_type(GLMessage::DataType::FLOAT);
-    arg_nz->add_floatvalue(nz);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glNormal3f(nx, ny, nz);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glOrthof(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glOrthof);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::FLOAT);
-    arg_l->add_floatvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::FLOAT);
-    arg_r->add_floatvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::FLOAT);
-    arg_b->add_floatvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::FLOAT);
-    arg_t->add_floatvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::FLOAT);
-    arg_n->add_floatvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::FLOAT);
-    arg_f->add_floatvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glOrthof(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointParameterf(GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointParameterf);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointParameterf(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointParameterfv(GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointParameterfv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointParameterfv(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointSize(GLfloat size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointSize);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::FLOAT);
-    arg_size->add_floatvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointSize(size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRotatef);
-
-    // copy argument angle
-    GLMessage_DataType *arg_angle = glmsg.add_args();
-    arg_angle->set_isarray(false);
-    arg_angle->set_type(GLMessage::DataType::FLOAT);
-    arg_angle->add_floatvalue(angle);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::FLOAT);
-    arg_z->add_floatvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRotatef(angle, x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glScalef(GLfloat x, GLfloat y, GLfloat z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glScalef);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::FLOAT);
-    arg_z->add_floatvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glScalef(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvf(GLenum target, GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvf);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvf(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvfv(GLenum target, GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvfv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvfv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTranslatef);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::FLOAT);
-    arg_z->add_floatvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTranslatef(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glAlphaFuncx(GLenum func, GLfixed ref) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glAlphaFuncx);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // copy argument ref
-    GLMessage_DataType *arg_ref = glmsg.add_args();
-    arg_ref->set_isarray(false);
-    arg_ref->set_type(GLMessage::DataType::INT);
-    arg_ref->add_intvalue(ref);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glAlphaFuncx(func, ref);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearColorx);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::INT);
-    arg_red->add_intvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::INT);
-    arg_green->add_intvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::INT);
-    arg_blue->add_intvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::INT);
-    arg_alpha->add_intvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearColorx(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearDepthx(GLfixed depth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearDepthx);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearDepthx(depth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClientActiveTexture(GLenum texture) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClientActiveTexture);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClientActiveTexture(texture);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClipPlanex(GLenum plane, const GLfixed * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClipPlanex);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClipPlanex(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColor4ub);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::BYTE);
-    arg_red->add_intvalue((int)red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::BYTE);
-    arg_green->add_intvalue((int)green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::BYTE);
-    arg_blue->add_intvalue((int)blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::BYTE);
-    arg_alpha->add_intvalue((int)alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColor4ub(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColor4x);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::INT);
-    arg_red->add_intvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::INT);
-    arg_green->add_intvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::INT);
-    arg_blue->add_intvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::INT);
-    arg_alpha->add_intvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColor4x(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColorPointer(GLint size, GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColorPointer);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColorPointer(size, type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDepthRangex(GLfixed n, GLfixed f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDepthRangex);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::INT);
-    arg_f->add_intvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDepthRangex(n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDisableClientState(GLenum array) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDisableClientState);
-
-    // copy argument array
-    GLMessage_DataType *arg_array = glmsg.add_args();
-    arg_array->set_isarray(false);
-    arg_array->set_type(GLMessage::DataType::ENUM);
-    arg_array->add_intvalue((int)array);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDisableClientState(array);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glEnableClientState(GLenum array) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glEnableClientState);
-
-    // copy argument array
-    GLMessage_DataType *arg_array = glmsg.add_args();
-    arg_array->set_isarray(false);
-    arg_array->set_type(GLMessage::DataType::ENUM);
-    arg_array->add_intvalue((int)array);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glEnableClientState(array);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFogx(GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFogx);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFogx(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFogxv(GLenum pname, const GLfixed * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFogxv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFogxv(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFrustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFrustumx);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::INT);
-    arg_l->add_intvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::INT);
-    arg_r->add_intvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::INT);
-    arg_b->add_intvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::INT);
-    arg_t->add_intvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::INT);
-    arg_f->add_intvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFrustumx(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetClipPlanex(GLenum plane, GLfixed * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetClipPlanex);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetClipPlanex(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetFixedv(GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFixedv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFixedv(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetLightxv(GLenum light, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetLightxv);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetLightxv(light, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetMaterialxv(GLenum face, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetMaterialxv);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetMaterialxv(face, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetPointerv(GLenum pname, void ** params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetPointerv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetPointerv(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexEnviv(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexEnviv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexEnviv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexEnvxv(GLenum target, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexEnvxv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexEnvxv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexParameterxv(GLenum target, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexParameterxv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexParameterxv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightModelx(GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightModelx);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightModelx(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightModelxv(GLenum pname, const GLfixed * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightModelxv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightModelxv(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightx(GLenum light, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightx);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightx(light, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightxv(GLenum light, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightxv);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightxv(light, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLineWidthx(GLfixed width) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLineWidthx);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLineWidthx(width);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLoadIdentity(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLoadIdentity);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLoadIdentity();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLoadMatrixx(const GLfixed * m) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLoadMatrixx);
-
-    // copy argument m
-    GLMessage_DataType *arg_m = glmsg.add_args();
-    arg_m->set_isarray(false);
-    arg_m->set_type(GLMessage::DataType::INT64);
-    arg_m->add_int64value((uintptr_t)m);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLoadMatrixx(m);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) m,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLogicOp(GLenum opcode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLogicOp);
-
-    // copy argument opcode
-    GLMessage_DataType *arg_opcode = glmsg.add_args();
-    arg_opcode->set_isarray(false);
-    arg_opcode->set_type(GLMessage::DataType::ENUM);
-    arg_opcode->add_intvalue((int)opcode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLogicOp(opcode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMaterialx(GLenum face, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMaterialx);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMaterialx(face, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMaterialxv(GLenum face, GLenum pname, const GLfixed * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMaterialxv);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMaterialxv(face, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMatrixMode(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMatrixMode);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMatrixMode(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultMatrixx(const GLfixed * m) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultMatrixx);
-
-    // copy argument m
-    GLMessage_DataType *arg_m = glmsg.add_args();
-    arg_m->set_isarray(false);
-    arg_m->set_type(GLMessage::DataType::INT64);
-    arg_m->add_int64value((uintptr_t)m);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultMatrixx(m);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) m,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord4x(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord4x);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::INT);
-    arg_s->add_intvalue(s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::INT);
-    arg_t->add_intvalue(t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::INT);
-    arg_r->add_intvalue(r);
-
-    // copy argument q
-    GLMessage_DataType *arg_q = glmsg.add_args();
-    arg_q->set_isarray(false);
-    arg_q->set_type(GLMessage::DataType::INT);
-    arg_q->add_intvalue(q);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord4x(texture, s, t, r, q);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glNormal3x);
-
-    // copy argument nx
-    GLMessage_DataType *arg_nx = glmsg.add_args();
-    arg_nx->set_isarray(false);
-    arg_nx->set_type(GLMessage::DataType::INT);
-    arg_nx->add_intvalue(nx);
-
-    // copy argument ny
-    GLMessage_DataType *arg_ny = glmsg.add_args();
-    arg_ny->set_isarray(false);
-    arg_ny->set_type(GLMessage::DataType::INT);
-    arg_ny->add_intvalue(ny);
-
-    // copy argument nz
-    GLMessage_DataType *arg_nz = glmsg.add_args();
-    arg_nz->set_isarray(false);
-    arg_nz->set_type(GLMessage::DataType::INT);
-    arg_nz->add_intvalue(nz);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glNormal3x(nx, ny, nz);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glNormalPointer(GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glNormalPointer);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glNormalPointer(type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glOrthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glOrthox);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::INT);
-    arg_l->add_intvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::INT);
-    arg_r->add_intvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::INT);
-    arg_b->add_intvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::INT);
-    arg_t->add_intvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::INT);
-    arg_f->add_intvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glOrthox(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointParameterx(GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointParameterx);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointParameterx(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointParameterxv(GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointParameterxv);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointParameterxv(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointSizex(GLfixed size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointSizex);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointSizex(size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPolygonOffsetx(GLfixed factor, GLfixed units) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPolygonOffsetx);
-
-    // copy argument factor
-    GLMessage_DataType *arg_factor = glmsg.add_args();
-    arg_factor->set_isarray(false);
-    arg_factor->set_type(GLMessage::DataType::INT);
-    arg_factor->add_intvalue(factor);
-
-    // copy argument units
-    GLMessage_DataType *arg_units = glmsg.add_args();
-    arg_units->set_isarray(false);
-    arg_units->set_type(GLMessage::DataType::INT);
-    arg_units->add_intvalue(units);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPolygonOffsetx(factor, units);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPopMatrix(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPopMatrix);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPopMatrix();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPushMatrix(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPushMatrix);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPushMatrix();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRotatex);
-
-    // copy argument angle
-    GLMessage_DataType *arg_angle = glmsg.add_args();
-    arg_angle->set_isarray(false);
-    arg_angle->set_type(GLMessage::DataType::INT);
-    arg_angle->add_intvalue(angle);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRotatex(angle, x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSampleCoveragex(GLclampx value, GLboolean invert) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSampleCoveragex);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // copy argument invert
-    GLMessage_DataType *arg_invert = glmsg.add_args();
-    arg_invert->set_isarray(false);
-    arg_invert->set_type(GLMessage::DataType::BOOL);
-    arg_invert->add_boolvalue(invert);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSampleCoveragex(value, invert);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glScalex(GLfixed x, GLfixed y, GLfixed z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glScalex);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glScalex(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glShadeModel(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glShadeModel);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glShadeModel(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoordPointer);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoordPointer(size, type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvi(GLenum target, GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvi);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvi(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvx(GLenum target, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvx);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvx(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnviv(GLenum target, GLenum pname, const GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnviv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnviv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvxv(GLenum target, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvxv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvxv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterx(GLenum target, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterx);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterx(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterxv(GLenum target, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterxv);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterxv(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTranslatex(GLfixed x, GLfixed y, GLfixed z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTranslatex);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTranslatex(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertexPointer);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertexPointer(size, type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-
-// Definitions for GL1Ext APIs
-
-void GLTrace_glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendEquationSeparateOES);
-
-    // copy argument modeRGB
-    GLMessage_DataType *arg_modeRGB = glmsg.add_args();
-    arg_modeRGB->set_isarray(false);
-    arg_modeRGB->set_type(GLMessage::DataType::ENUM);
-    arg_modeRGB->add_intvalue((int)modeRGB);
-
-    // copy argument modeAlpha
-    GLMessage_DataType *arg_modeAlpha = glmsg.add_args();
-    arg_modeAlpha->set_isarray(false);
-    arg_modeAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_modeAlpha->add_intvalue((int)modeAlpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendEquationSeparateOES(modeRGB, modeAlpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendFuncSeparateOES);
-
-    // copy argument srcRGB
-    GLMessage_DataType *arg_srcRGB = glmsg.add_args();
-    arg_srcRGB->set_isarray(false);
-    arg_srcRGB->set_type(GLMessage::DataType::ENUM);
-    arg_srcRGB->add_intvalue((int)srcRGB);
-
-    // copy argument dstRGB
-    GLMessage_DataType *arg_dstRGB = glmsg.add_args();
-    arg_dstRGB->set_isarray(false);
-    arg_dstRGB->set_type(GLMessage::DataType::ENUM);
-    arg_dstRGB->add_intvalue((int)dstRGB);
-
-    // copy argument srcAlpha
-    GLMessage_DataType *arg_srcAlpha = glmsg.add_args();
-    arg_srcAlpha->set_isarray(false);
-    arg_srcAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_srcAlpha->add_intvalue((int)srcAlpha);
-
-    // copy argument dstAlpha
-    GLMessage_DataType *arg_dstAlpha = glmsg.add_args();
-    arg_dstAlpha->set_isarray(false);
-    arg_dstAlpha->set_type(GLMessage::DataType::ENUM);
-    arg_dstAlpha->add_intvalue((int)dstAlpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendFuncSeparateOES(srcRGB, dstRGB, srcAlpha, dstAlpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glBlendEquationOES(GLenum mode) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBlendEquationOES);
-
-    // copy argument mode
-    GLMessage_DataType *arg_mode = glmsg.add_args();
-    arg_mode->set_isarray(false);
-    arg_mode->set_type(GLMessage::DataType::ENUM);
-    arg_mode->add_intvalue((int)mode);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBlendEquationOES(mode);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord1bOES(GLenum texture, GLbyte s) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord1bOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord1bOES(texture, s);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord1bvOES(GLenum texture, const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord1bvOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord1bvOES(texture, coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord2bOES(GLenum texture, GLbyte s, GLbyte t) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord2bOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::BYTE);
-    arg_t->add_intvalue((int)t);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord2bOES(texture, s, t);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord2bvOES(GLenum texture, const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord2bvOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord2bvOES(texture, coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord3bOES(GLenum texture, GLbyte s, GLbyte t, GLbyte r) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord3bOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::BYTE);
-    arg_t->add_intvalue((int)t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::BYTE);
-    arg_r->add_intvalue((int)r);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord3bOES(texture, s, t, r);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord3bvOES(GLenum texture, const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord3bvOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord3bvOES(texture, coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord4bOES(GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord4bOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::BYTE);
-    arg_t->add_intvalue((int)t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::BYTE);
-    arg_r->add_intvalue((int)r);
-
-    // copy argument q
-    GLMessage_DataType *arg_q = glmsg.add_args();
-    arg_q->set_isarray(false);
-    arg_q->set_type(GLMessage::DataType::BYTE);
-    arg_q->add_intvalue((int)q);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord4bOES(texture, s, t, r, q);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord4bvOES(GLenum texture, const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord4bvOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord4bvOES(texture, coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord1bOES(GLbyte s) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord1bOES);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord1bOES(s);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord1bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord1bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord1bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord2bOES(GLbyte s, GLbyte t) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord2bOES);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::BYTE);
-    arg_t->add_intvalue((int)t);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord2bOES(s, t);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord2bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord2bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord2bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord3bOES(GLbyte s, GLbyte t, GLbyte r) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord3bOES);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::BYTE);
-    arg_t->add_intvalue((int)t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::BYTE);
-    arg_r->add_intvalue((int)r);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord3bOES(s, t, r);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord3bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord3bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord3bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord4bOES(GLbyte s, GLbyte t, GLbyte r, GLbyte q) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord4bOES);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::BYTE);
-    arg_s->add_intvalue((int)s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::BYTE);
-    arg_t->add_intvalue((int)t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::BYTE);
-    arg_r->add_intvalue((int)r);
-
-    // copy argument q
-    GLMessage_DataType *arg_q = glmsg.add_args();
-    arg_q->set_isarray(false);
-    arg_q->set_type(GLMessage::DataType::BYTE);
-    arg_q->add_intvalue((int)q);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord4bOES(s, t, r, q);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexCoord4bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexCoord4bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexCoord4bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertex2bOES(GLbyte x) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertex2bOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::BYTE);
-    arg_x->add_intvalue((int)x);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertex2bOES(x);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertex2bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertex2bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertex2bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertex3bOES(GLbyte x, GLbyte y) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertex3bOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::BYTE);
-    arg_x->add_intvalue((int)x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::BYTE);
-    arg_y->add_intvalue((int)y);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertex3bOES(x, y);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertex3bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertex3bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertex3bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertex4bOES(GLbyte x, GLbyte y, GLbyte z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertex4bOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::BYTE);
-    arg_x->add_intvalue((int)x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::BYTE);
-    arg_y->add_intvalue((int)y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::BYTE);
-    arg_z->add_intvalue((int)z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertex4bOES(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glVertex4bvOES(const GLbyte * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glVertex4bvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glVertex4bvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexsOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexsOES(x, y, z, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexiOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexiOES(x, y, z, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexxOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexxOES(x, y, z, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexsvOES(const GLshort * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexsvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexsvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexivOES(const GLint * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexivOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexivOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexxvOES(const GLfixed * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexxvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexxvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexfOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::FLOAT);
-    arg_x->add_floatvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::FLOAT);
-    arg_y->add_floatvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::FLOAT);
-    arg_z->add_floatvalue(z);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::FLOAT);
-    arg_width->add_floatvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::FLOAT);
-    arg_height->add_floatvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexfOES(x, y, z, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDrawTexfvOES(const GLfloat * coords) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDrawTexfvOES);
-
-    // copy argument coords
-    GLMessage_DataType *arg_coords = glmsg.add_args();
-    arg_coords->set_isarray(false);
-    arg_coords->set_type(GLMessage::DataType::INT64);
-    arg_coords->add_int64value((uintptr_t)coords);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDrawTexfvOES(coords);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) coords,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glAlphaFuncxOES(GLenum func, GLfixed ref) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glAlphaFuncxOES);
-
-    // copy argument func
-    GLMessage_DataType *arg_func = glmsg.add_args();
-    arg_func->set_isarray(false);
-    arg_func->set_type(GLMessage::DataType::ENUM);
-    arg_func->add_intvalue((int)func);
-
-    // copy argument ref
-    GLMessage_DataType *arg_ref = glmsg.add_args();
-    arg_ref->set_isarray(false);
-    arg_ref->set_type(GLMessage::DataType::INT);
-    arg_ref->add_intvalue(ref);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glAlphaFuncxOES(func, ref);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearColorxOES(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearColorxOES);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::INT);
-    arg_red->add_intvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::INT);
-    arg_green->add_intvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::INT);
-    arg_blue->add_intvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::INT);
-    arg_alpha->add_intvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearColorxOES(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClearDepthxOES(GLfixed depth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearDepthxOES);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::INT);
-    arg_depth->add_intvalue(depth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearDepthxOES(depth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClipPlanexOES(GLenum plane, const GLfixed * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClipPlanexOES);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClipPlanexOES(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glColor4xOES(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glColor4xOES);
-
-    // copy argument red
-    GLMessage_DataType *arg_red = glmsg.add_args();
-    arg_red->set_isarray(false);
-    arg_red->set_type(GLMessage::DataType::INT);
-    arg_red->add_intvalue(red);
-
-    // copy argument green
-    GLMessage_DataType *arg_green = glmsg.add_args();
-    arg_green->set_isarray(false);
-    arg_green->set_type(GLMessage::DataType::INT);
-    arg_green->add_intvalue(green);
-
-    // copy argument blue
-    GLMessage_DataType *arg_blue = glmsg.add_args();
-    arg_blue->set_isarray(false);
-    arg_blue->set_type(GLMessage::DataType::INT);
-    arg_blue->add_intvalue(blue);
-
-    // copy argument alpha
-    GLMessage_DataType *arg_alpha = glmsg.add_args();
-    arg_alpha->set_isarray(false);
-    arg_alpha->set_type(GLMessage::DataType::INT);
-    arg_alpha->add_intvalue(alpha);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glColor4xOES(red, green, blue, alpha);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDepthRangexOES(GLfixed n, GLfixed f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDepthRangexOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::INT);
-    arg_f->add_intvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDepthRangexOES(n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFogxOES(GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFogxOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFogxOES(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFogxvOES(GLenum pname, const GLfixed * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFogxvOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFogxvOES(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFrustumxOES(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFrustumxOES);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::INT);
-    arg_l->add_intvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::INT);
-    arg_r->add_intvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::INT);
-    arg_b->add_intvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::INT);
-    arg_t->add_intvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::INT);
-    arg_f->add_intvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFrustumxOES(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetClipPlanexOES(GLenum plane, GLfixed * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetClipPlanexOES);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetClipPlanexOES(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetFixedvOES(GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFixedvOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFixedvOES(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexEnvxvOES(GLenum target, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexEnvxvOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexEnvxvOES(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexParameterxvOES(GLenum target, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexParameterxvOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexParameterxvOES(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightModelxOES(GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightModelxOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightModelxOES(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightModelxvOES(GLenum pname, const GLfixed * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightModelxvOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightModelxvOES(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightxOES(GLenum light, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightxOES);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightxOES(light, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLightxvOES(GLenum light, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLightxvOES);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLightxvOES(light, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLineWidthxOES(GLfixed width) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLineWidthxOES);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLineWidthxOES(width);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLoadMatrixxOES(const GLfixed * m) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLoadMatrixxOES);
-
-    // copy argument m
-    GLMessage_DataType *arg_m = glmsg.add_args();
-    arg_m->set_isarray(false);
-    arg_m->set_type(GLMessage::DataType::INT64);
-    arg_m->add_int64value((uintptr_t)m);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLoadMatrixxOES(m);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) m,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMaterialxOES(GLenum face, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMaterialxOES);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMaterialxOES(face, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMaterialxvOES(GLenum face, GLenum pname, const GLfixed * param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMaterialxvOES);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT64);
-    arg_param->add_int64value((uintptr_t)param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMaterialxvOES(face, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) param,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultMatrixxOES(const GLfixed * m) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultMatrixxOES);
-
-    // copy argument m
-    GLMessage_DataType *arg_m = glmsg.add_args();
-    arg_m->set_isarray(false);
-    arg_m->set_type(GLMessage::DataType::INT64);
-    arg_m->add_int64value((uintptr_t)m);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultMatrixxOES(m);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) m,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMultiTexCoord4xOES(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMultiTexCoord4xOES);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::ENUM);
-    arg_texture->add_intvalue((int)texture);
-
-    // copy argument s
-    GLMessage_DataType *arg_s = glmsg.add_args();
-    arg_s->set_isarray(false);
-    arg_s->set_type(GLMessage::DataType::INT);
-    arg_s->add_intvalue(s);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::INT);
-    arg_t->add_intvalue(t);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::INT);
-    arg_r->add_intvalue(r);
-
-    // copy argument q
-    GLMessage_DataType *arg_q = glmsg.add_args();
-    arg_q->set_isarray(false);
-    arg_q->set_type(GLMessage::DataType::INT);
-    arg_q->add_intvalue(q);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMultiTexCoord4xOES(texture, s, t, r, q);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glNormal3xOES(GLfixed nx, GLfixed ny, GLfixed nz) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glNormal3xOES);
-
-    // copy argument nx
-    GLMessage_DataType *arg_nx = glmsg.add_args();
-    arg_nx->set_isarray(false);
-    arg_nx->set_type(GLMessage::DataType::INT);
-    arg_nx->add_intvalue(nx);
-
-    // copy argument ny
-    GLMessage_DataType *arg_ny = glmsg.add_args();
-    arg_ny->set_isarray(false);
-    arg_ny->set_type(GLMessage::DataType::INT);
-    arg_ny->add_intvalue(ny);
-
-    // copy argument nz
-    GLMessage_DataType *arg_nz = glmsg.add_args();
-    arg_nz->set_isarray(false);
-    arg_nz->set_type(GLMessage::DataType::INT);
-    arg_nz->add_intvalue(nz);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glNormal3xOES(nx, ny, nz);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glOrthoxOES(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glOrthoxOES);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::INT);
-    arg_l->add_intvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::INT);
-    arg_r->add_intvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::INT);
-    arg_b->add_intvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::INT);
-    arg_t->add_intvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::INT);
-    arg_f->add_intvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glOrthoxOES(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointParameterxvOES(GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointParameterxvOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointParameterxvOES(pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointSizexOES(GLfixed size) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointSizexOES);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointSizexOES(size);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPolygonOffsetxOES(GLfixed factor, GLfixed units) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPolygonOffsetxOES);
-
-    // copy argument factor
-    GLMessage_DataType *arg_factor = glmsg.add_args();
-    arg_factor->set_isarray(false);
-    arg_factor->set_type(GLMessage::DataType::INT);
-    arg_factor->add_intvalue(factor);
-
-    // copy argument units
-    GLMessage_DataType *arg_units = glmsg.add_args();
-    arg_units->set_isarray(false);
-    arg_units->set_type(GLMessage::DataType::INT);
-    arg_units->add_intvalue(units);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPolygonOffsetxOES(factor, units);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRotatexOES(GLfixed angle, GLfixed x, GLfixed y, GLfixed z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRotatexOES);
-
-    // copy argument angle
-    GLMessage_DataType *arg_angle = glmsg.add_args();
-    arg_angle->set_isarray(false);
-    arg_angle->set_type(GLMessage::DataType::INT);
-    arg_angle->add_intvalue(angle);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRotatexOES(angle, x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSampleCoverageOES(GLfixed value, GLboolean invert) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSampleCoverageOES);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // copy argument invert
-    GLMessage_DataType *arg_invert = glmsg.add_args();
-    arg_invert->set_isarray(false);
-    arg_invert->set_type(GLMessage::DataType::BOOL);
-    arg_invert->add_boolvalue(invert);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSampleCoverageOES(value, invert);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glScalexOES(GLfixed x, GLfixed y, GLfixed z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glScalexOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glScalexOES(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvxOES(GLenum target, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvxOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvxOES(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexEnvxvOES(GLenum target, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexEnvxvOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexEnvxvOES(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterxOES(GLenum target, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterxOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterxOES(target, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexParameterxvOES(GLenum target, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexParameterxvOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexParameterxvOES(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTranslatexOES(GLfixed x, GLfixed y, GLfixed z) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTranslatexOES);
-
-    // copy argument x
-    GLMessage_DataType *arg_x = glmsg.add_args();
-    arg_x->set_isarray(false);
-    arg_x->set_type(GLMessage::DataType::INT);
-    arg_x->add_intvalue(x);
-
-    // copy argument y
-    GLMessage_DataType *arg_y = glmsg.add_args();
-    arg_y->set_isarray(false);
-    arg_y->set_type(GLMessage::DataType::INT);
-    arg_y->add_intvalue(y);
-
-    // copy argument z
-    GLMessage_DataType *arg_z = glmsg.add_args();
-    arg_z->set_isarray(false);
-    arg_z->set_type(GLMessage::DataType::INT);
-    arg_z->add_intvalue(z);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTranslatexOES(x, y, z);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetLightxvOES(GLenum light, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetLightxvOES);
-
-    // copy argument light
-    GLMessage_DataType *arg_light = glmsg.add_args();
-    arg_light->set_isarray(false);
-    arg_light->set_type(GLMessage::DataType::ENUM);
-    arg_light->add_intvalue((int)light);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetLightxvOES(light, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetMaterialxvOES(GLenum face, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetMaterialxvOES);
-
-    // copy argument face
-    GLMessage_DataType *arg_face = glmsg.add_args();
-    arg_face->set_isarray(false);
-    arg_face->set_type(GLMessage::DataType::ENUM);
-    arg_face->add_intvalue((int)face);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetMaterialxvOES(face, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointParameterxOES(GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointParameterxOES);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointParameterxOES(pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glSampleCoveragexOES(GLclampx value, GLboolean invert) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glSampleCoveragexOES);
-
-    // copy argument value
-    GLMessage_DataType *arg_value = glmsg.add_args();
-    arg_value->set_isarray(false);
-    arg_value->set_type(GLMessage::DataType::INT);
-    arg_value->add_intvalue(value);
-
-    // copy argument invert
-    GLMessage_DataType *arg_invert = glmsg.add_args();
-    arg_invert->set_isarray(false);
-    arg_invert->set_type(GLMessage::DataType::BOOL);
-    arg_invert->add_boolvalue(invert);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glSampleCoveragexOES(value, invert);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexGenxvOES(GLenum coord, GLenum pname, GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexGenxvOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexGenxvOES(coord, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexGenxOES(GLenum coord, GLenum pname, GLfixed param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexGenxOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexGenxOES(coord, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexGenxvOES(GLenum coord, GLenum pname, const GLfixed * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexGenxvOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexGenxvOES(coord, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsRenderbufferOES(GLuint renderbuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsRenderbufferOES);
-
-    // copy argument renderbuffer
-    GLMessage_DataType *arg_renderbuffer = glmsg.add_args();
-    arg_renderbuffer->set_isarray(false);
-    arg_renderbuffer->set_type(GLMessage::DataType::INT);
-    arg_renderbuffer->add_intvalue(renderbuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsRenderbufferOES(renderbuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glBindRenderbufferOES(GLenum target, GLuint renderbuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindRenderbufferOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument renderbuffer
-    GLMessage_DataType *arg_renderbuffer = glmsg.add_args();
-    arg_renderbuffer->set_isarray(false);
-    arg_renderbuffer->set_type(GLMessage::DataType::INT);
-    arg_renderbuffer->add_intvalue(renderbuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindRenderbufferOES(target, renderbuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteRenderbuffersOES(GLsizei n, const GLuint * renderbuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteRenderbuffersOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument renderbuffers
-    GLMessage_DataType *arg_renderbuffers = glmsg.add_args();
-    arg_renderbuffers->set_isarray(false);
-    arg_renderbuffers->set_type(GLMessage::DataType::INT64);
-    arg_renderbuffers->add_int64value((uintptr_t)renderbuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteRenderbuffersOES(n, renderbuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) renderbuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenRenderbuffersOES(GLsizei n, GLuint * renderbuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenRenderbuffersOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument renderbuffers
-    GLMessage_DataType *arg_renderbuffers = glmsg.add_args();
-    arg_renderbuffers->set_isarray(false);
-    arg_renderbuffers->set_type(GLMessage::DataType::INT64);
-    arg_renderbuffers->add_int64value((uintptr_t)renderbuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenRenderbuffersOES(n, renderbuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) renderbuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glRenderbufferStorageOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument internalformat
-    GLMessage_DataType *arg_internalformat = glmsg.add_args();
-    arg_internalformat->set_isarray(false);
-    arg_internalformat->set_type(GLMessage::DataType::ENUM);
-    arg_internalformat->add_intvalue((int)internalformat);
-
-    // copy argument width
-    GLMessage_DataType *arg_width = glmsg.add_args();
-    arg_width->set_isarray(false);
-    arg_width->set_type(GLMessage::DataType::INT);
-    arg_width->add_intvalue(width);
-
-    // copy argument height
-    GLMessage_DataType *arg_height = glmsg.add_args();
-    arg_height->set_isarray(false);
-    arg_height->set_type(GLMessage::DataType::INT);
-    arg_height->add_intvalue(height);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glRenderbufferStorageOES(target, internalformat, width, height);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetRenderbufferParameterivOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetRenderbufferParameterivOES(target, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLboolean GLTrace_glIsFramebufferOES(GLuint framebuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glIsFramebufferOES);
-
-    // copy argument framebuffer
-    GLMessage_DataType *arg_framebuffer = glmsg.add_args();
-    arg_framebuffer->set_isarray(false);
-    arg_framebuffer->set_type(GLMessage::DataType::INT);
-    arg_framebuffer->add_intvalue(framebuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLboolean retValue = glContext->hooks->gl.glIsFramebufferOES(framebuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::BOOL);
-    rt->add_boolvalue(retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glBindFramebufferOES(GLenum target, GLuint framebuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glBindFramebufferOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument framebuffer
-    GLMessage_DataType *arg_framebuffer = glmsg.add_args();
-    arg_framebuffer->set_isarray(false);
-    arg_framebuffer->set_type(GLMessage::DataType::INT);
-    arg_framebuffer->add_intvalue(framebuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glBindFramebufferOES(target, framebuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDeleteFramebuffersOES(GLsizei n, const GLuint * framebuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDeleteFramebuffersOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument framebuffers
-    GLMessage_DataType *arg_framebuffers = glmsg.add_args();
-    arg_framebuffers->set_isarray(false);
-    arg_framebuffers->set_type(GLMessage::DataType::INT64);
-    arg_framebuffers->add_int64value((uintptr_t)framebuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDeleteFramebuffersOES(n, framebuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) framebuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenFramebuffersOES(GLsizei n, GLuint * framebuffers) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenFramebuffersOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::INT);
-    arg_n->add_intvalue(n);
-
-    // copy argument framebuffers
-    GLMessage_DataType *arg_framebuffers = glmsg.add_args();
-    arg_framebuffers->set_isarray(false);
-    arg_framebuffers->set_type(GLMessage::DataType::INT64);
-    arg_framebuffers->add_int64value((uintptr_t)framebuffers);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenFramebuffersOES(n, framebuffers);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) framebuffers,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLenum GLTrace_glCheckFramebufferStatusOES(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCheckFramebufferStatusOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLenum retValue = glContext->hooks->gl.glCheckFramebufferStatusOES(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::ENUM);
-    rt->add_intvalue((int)retValue);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferRenderbufferOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument renderbuffertarget
-    GLMessage_DataType *arg_renderbuffertarget = glmsg.add_args();
-    arg_renderbuffertarget->set_isarray(false);
-    arg_renderbuffertarget->set_type(GLMessage::DataType::ENUM);
-    arg_renderbuffertarget->add_intvalue((int)renderbuffertarget);
-
-    // copy argument renderbuffer
-    GLMessage_DataType *arg_renderbuffer = glmsg.add_args();
-    arg_renderbuffer->set_isarray(false);
-    arg_renderbuffer->set_type(GLMessage::DataType::INT);
-    arg_renderbuffer->add_intvalue(renderbuffer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferRenderbufferOES(target, attachment, renderbuffertarget, renderbuffer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFramebufferTexture2DOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument textarget
-    GLMessage_DataType *arg_textarget = glmsg.add_args();
-    arg_textarget->set_isarray(false);
-    arg_textarget->set_type(GLMessage::DataType::ENUM);
-    arg_textarget->add_intvalue((int)textarget);
-
-    // copy argument texture
-    GLMessage_DataType *arg_texture = glmsg.add_args();
-    arg_texture->set_isarray(false);
-    arg_texture->set_type(GLMessage::DataType::INT);
-    arg_texture->add_intvalue(texture);
-
-    // copy argument level
-    GLMessage_DataType *arg_level = glmsg.add_args();
-    arg_level->set_isarray(false);
-    arg_level->set_type(GLMessage::DataType::INT);
-    arg_level->add_intvalue(level);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFramebufferTexture2DOES(target, attachment, textarget, texture, level);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetFramebufferAttachmentParameterivOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // copy argument attachment
-    GLMessage_DataType *arg_attachment = glmsg.add_args();
-    arg_attachment->set_isarray(false);
-    arg_attachment->set_type(GLMessage::DataType::ENUM);
-    arg_attachment->add_intvalue((int)attachment);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetFramebufferAttachmentParameterivOES(target, attachment, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGenerateMipmapOES(GLenum target) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGenerateMipmapOES);
-
-    // copy argument target
-    GLMessage_DataType *arg_target = glmsg.add_args();
-    arg_target->set_isarray(false);
-    arg_target->set_type(GLMessage::DataType::ENUM);
-    arg_target->add_intvalue((int)target);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGenerateMipmapOES(target);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glCurrentPaletteMatrixOES(GLuint matrixpaletteindex) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glCurrentPaletteMatrixOES);
-
-    // copy argument matrixpaletteindex
-    GLMessage_DataType *arg_matrixpaletteindex = glmsg.add_args();
-    arg_matrixpaletteindex->set_isarray(false);
-    arg_matrixpaletteindex->set_type(GLMessage::DataType::INT);
-    arg_matrixpaletteindex->add_intvalue(matrixpaletteindex);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glCurrentPaletteMatrixOES(matrixpaletteindex);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glLoadPaletteFromModelViewMatrixOES(void) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glLoadPaletteFromModelViewMatrixOES);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glLoadPaletteFromModelViewMatrixOES();
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glMatrixIndexPointerOES(GLint size, GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glMatrixIndexPointerOES);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glMatrixIndexPointerOES(size, type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glWeightPointerOES(GLint size, GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glWeightPointerOES);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glWeightPointerOES(size, type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glPointSizePointerOES(GLenum type, GLsizei stride, const void * pointer) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glPointSizePointerOES);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument pointer
-    GLMessage_DataType *arg_pointer = glmsg.add_args();
-    arg_pointer->set_isarray(false);
-    arg_pointer->set_type(GLMessage::DataType::INT64);
-    arg_pointer->add_int64value((uintptr_t)pointer);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glPointSizePointerOES(type, stride, pointer);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) pointer,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-GLbitfield GLTrace_glQueryMatrixxOES(GLfixed * mantissa, GLint * exponent) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glQueryMatrixxOES);
-
-    // copy argument mantissa
-    GLMessage_DataType *arg_mantissa = glmsg.add_args();
-    arg_mantissa->set_isarray(false);
-    arg_mantissa->set_type(GLMessage::DataType::INT64);
-    arg_mantissa->add_int64value((uintptr_t)mantissa);
-
-    // copy argument exponent
-    GLMessage_DataType *arg_exponent = glmsg.add_args();
-    arg_exponent->set_isarray(false);
-    arg_exponent->set_type(GLMessage::DataType::INT64);
-    arg_exponent->add_int64value((uintptr_t)exponent);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    GLbitfield retValue = glContext->hooks->gl.glQueryMatrixxOES(mantissa, exponent);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::INT);
-    rt->add_intvalue(retValue);
-
-    void *pointerArgs[] = {
-        (void *) mantissa,
-        (void *) exponent,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-
-    return retValue;
-}
-
-void GLTrace_glClearDepthfOES(GLclampf depth) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClearDepthfOES);
-
-    // copy argument depth
-    GLMessage_DataType *arg_depth = glmsg.add_args();
-    arg_depth->set_isarray(false);
-    arg_depth->set_type(GLMessage::DataType::FLOAT);
-    arg_depth->add_floatvalue(depth);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClearDepthfOES(depth);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClipPlanefOES(GLenum plane, const GLfloat * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClipPlanefOES);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClipPlanefOES(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glDepthRangefOES(GLclampf n, GLclampf f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glDepthRangefOES);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::FLOAT);
-    arg_n->add_floatvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::FLOAT);
-    arg_f->add_floatvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glDepthRangefOES(n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glFrustumfOES(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glFrustumfOES);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::FLOAT);
-    arg_l->add_floatvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::FLOAT);
-    arg_r->add_floatvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::FLOAT);
-    arg_b->add_floatvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::FLOAT);
-    arg_t->add_floatvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::FLOAT);
-    arg_n->add_floatvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::FLOAT);
-    arg_f->add_floatvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glFrustumfOES(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetClipPlanefOES(GLenum plane, GLfloat * equation) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetClipPlanefOES);
-
-    // copy argument plane
-    GLMessage_DataType *arg_plane = glmsg.add_args();
-    arg_plane->set_isarray(false);
-    arg_plane->set_type(GLMessage::DataType::ENUM);
-    arg_plane->add_intvalue((int)plane);
-
-    // copy argument equation
-    GLMessage_DataType *arg_equation = glmsg.add_args();
-    arg_equation->set_isarray(false);
-    arg_equation->set_type(GLMessage::DataType::INT64);
-    arg_equation->add_int64value((uintptr_t)equation);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetClipPlanefOES(plane, equation);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) equation,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glOrthofOES(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glOrthofOES);
-
-    // copy argument l
-    GLMessage_DataType *arg_l = glmsg.add_args();
-    arg_l->set_isarray(false);
-    arg_l->set_type(GLMessage::DataType::FLOAT);
-    arg_l->add_floatvalue(l);
-
-    // copy argument r
-    GLMessage_DataType *arg_r = glmsg.add_args();
-    arg_r->set_isarray(false);
-    arg_r->set_type(GLMessage::DataType::FLOAT);
-    arg_r->add_floatvalue(r);
-
-    // copy argument b
-    GLMessage_DataType *arg_b = glmsg.add_args();
-    arg_b->set_isarray(false);
-    arg_b->set_type(GLMessage::DataType::FLOAT);
-    arg_b->add_floatvalue(b);
-
-    // copy argument t
-    GLMessage_DataType *arg_t = glmsg.add_args();
-    arg_t->set_isarray(false);
-    arg_t->set_type(GLMessage::DataType::FLOAT);
-    arg_t->add_floatvalue(t);
-
-    // copy argument n
-    GLMessage_DataType *arg_n = glmsg.add_args();
-    arg_n->set_isarray(false);
-    arg_n->set_type(GLMessage::DataType::FLOAT);
-    arg_n->add_floatvalue(n);
-
-    // copy argument f
-    GLMessage_DataType *arg_f = glmsg.add_args();
-    arg_f->set_isarray(false);
-    arg_f->set_type(GLMessage::DataType::FLOAT);
-    arg_f->add_floatvalue(f);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glOrthofOES(l, r, b, t, n, f);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexGenfOES(GLenum coord, GLenum pname, GLfloat param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexGenfOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::FLOAT);
-    arg_param->add_floatvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexGenfOES(coord, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexGenfvOES(GLenum coord, GLenum pname, const GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexGenfvOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexGenfvOES(coord, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexGeniOES(GLenum coord, GLenum pname, GLint param) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexGeniOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument param
-    GLMessage_DataType *arg_param = glmsg.add_args();
-    arg_param->set_isarray(false);
-    arg_param->set_type(GLMessage::DataType::INT);
-    arg_param->add_intvalue(param);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexGeniOES(coord, pname, param);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glTexGenivOES(GLenum coord, GLenum pname, const GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glTexGenivOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glTexGenivOES(coord, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexGenfvOES(GLenum coord, GLenum pname, GLfloat * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexGenfvOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexGenfvOES(coord, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glGetTexGenivOES(GLenum coord, GLenum pname, GLint * params) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glGetTexGenivOES);
-
-    // copy argument coord
-    GLMessage_DataType *arg_coord = glmsg.add_args();
-    arg_coord->set_isarray(false);
-    arg_coord->set_type(GLMessage::DataType::ENUM);
-    arg_coord->add_intvalue((int)coord);
-
-    // copy argument pname
-    GLMessage_DataType *arg_pname = glmsg.add_args();
-    arg_pname->set_isarray(false);
-    arg_pname->set_type(GLMessage::DataType::ENUM);
-    arg_pname->add_intvalue((int)pname);
-
-    // copy argument params
-    GLMessage_DataType *arg_params = glmsg.add_args();
-    arg_params->set_isarray(false);
-    arg_params->set_type(GLMessage::DataType::INT64);
-    arg_params->add_int64value((uintptr_t)params);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glGetTexGenivOES(coord, pname, params);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) params,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClipPlanefIMG(GLenum p, const GLfloat * eqn) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClipPlanefIMG);
-
-    // copy argument p
-    GLMessage_DataType *arg_p = glmsg.add_args();
-    arg_p->set_isarray(false);
-    arg_p->set_type(GLMessage::DataType::ENUM);
-    arg_p->add_intvalue((int)p);
-
-    // copy argument eqn
-    GLMessage_DataType *arg_eqn = glmsg.add_args();
-    arg_eqn->set_isarray(false);
-    arg_eqn->set_type(GLMessage::DataType::INT64);
-    arg_eqn->add_int64value((uintptr_t)eqn);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClipPlanefIMG(p, eqn);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) eqn,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-void GLTrace_glClipPlanexIMG(GLenum p, const GLfixed * eqn) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::glClipPlanexIMG);
-
-    // copy argument p
-    GLMessage_DataType *arg_p = glmsg.add_args();
-    arg_p->set_isarray(false);
-    arg_p->set_type(GLMessage::DataType::ENUM);
-    arg_p->add_intvalue((int)p);
-
-    // copy argument eqn
-    GLMessage_DataType *arg_eqn = glmsg.add_args();
-    arg_eqn->set_isarray(false);
-    arg_eqn->set_type(GLMessage::DataType::INT64);
-    arg_eqn->add_int64value((uintptr_t)eqn);
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-    glContext->hooks->gl.glClipPlanexIMG(p, eqn);
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-
-    void *pointerArgs[] = {
-        (void *) eqn,
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-}
-
-
-}; // namespace gltrace
-}; // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_api.h b/opengl/libs/GLES_trace/src/gltrace_api.h
deleted file mode 100644
index a9ca3c4..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_api.h
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- *
- * THIS FILE WAS GENERATED BY A SCRIPT. DO NOT EDIT.
- */
-
-namespace android {
-namespace gltrace {
-
-// Declarations for GL2 APIs
-
-void GLTrace_glActiveTexture(GLenum texture);
-void GLTrace_glAttachShader(GLuint program, GLuint shader);
-void GLTrace_glBindAttribLocation(GLuint program, GLuint index, const GLchar * name);
-void GLTrace_glBindBuffer(GLenum target, GLuint buffer);
-void GLTrace_glBindFramebuffer(GLenum target, GLuint framebuffer);
-void GLTrace_glBindRenderbuffer(GLenum target, GLuint renderbuffer);
-void GLTrace_glBindTexture(GLenum target, GLuint texture);
-void GLTrace_glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void GLTrace_glBlendEquation(GLenum mode);
-void GLTrace_glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
-void GLTrace_glBlendFunc(GLenum sfactor, GLenum dfactor);
-void GLTrace_glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
-void GLTrace_glBufferData(GLenum target, GLsizeiptr size, const void * data, GLenum usage);
-void GLTrace_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void * data);
-GLenum GLTrace_glCheckFramebufferStatus(GLenum target);
-void GLTrace_glClear(GLbitfield mask);
-void GLTrace_glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void GLTrace_glClearDepthf(GLfloat d);
-void GLTrace_glClearStencil(GLint s);
-void GLTrace_glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-void GLTrace_glCompileShader(GLuint shader);
-void GLTrace_glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data);
-void GLTrace_glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data);
-void GLTrace_glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-void GLTrace_glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-GLuint GLTrace_glCreateProgram(void);
-GLuint GLTrace_glCreateShader(GLenum type);
-void GLTrace_glCullFace(GLenum mode);
-void GLTrace_glDeleteBuffers(GLsizei n, const GLuint * buffers);
-void GLTrace_glDeleteFramebuffers(GLsizei n, const GLuint * framebuffers);
-void GLTrace_glDeleteProgram(GLuint program);
-void GLTrace_glDeleteRenderbuffers(GLsizei n, const GLuint * renderbuffers);
-void GLTrace_glDeleteShader(GLuint shader);
-void GLTrace_glDeleteTextures(GLsizei n, const GLuint * textures);
-void GLTrace_glDepthFunc(GLenum func);
-void GLTrace_glDepthMask(GLboolean flag);
-void GLTrace_glDepthRangef(GLfloat n, GLfloat f);
-void GLTrace_glDetachShader(GLuint program, GLuint shader);
-void GLTrace_glDisable(GLenum cap);
-void GLTrace_glDisableVertexAttribArray(GLuint index);
-void GLTrace_glDrawArrays(GLenum mode, GLint first, GLsizei count);
-void GLTrace_glDrawElements(GLenum mode, GLsizei count, GLenum type, const void * indices);
-void GLTrace_glEnable(GLenum cap);
-void GLTrace_glEnableVertexAttribArray(GLuint index);
-void GLTrace_glFinish(void);
-void GLTrace_glFlush(void);
-void GLTrace_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-void GLTrace_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-void GLTrace_glFrontFace(GLenum mode);
-void GLTrace_glGenBuffers(GLsizei n, GLuint * buffers);
-void GLTrace_glGenerateMipmap(GLenum target);
-void GLTrace_glGenFramebuffers(GLsizei n, GLuint * framebuffers);
-void GLTrace_glGenRenderbuffers(GLsizei n, GLuint * renderbuffers);
-void GLTrace_glGenTextures(GLsizei n, GLuint * textures);
-void GLTrace_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
-void GLTrace_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name);
-void GLTrace_glGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders);
-GLint GLTrace_glGetAttribLocation(GLuint program, const GLchar * name);
-void GLTrace_glGetBooleanv(GLenum pname, GLboolean * data);
-void GLTrace_glGetBufferParameteriv(GLenum target, GLenum pname, GLint * params);
-GLenum GLTrace_glGetError(void);
-void GLTrace_glGetFloatv(GLenum pname, GLfloat * data);
-void GLTrace_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint * params);
-void GLTrace_glGetIntegerv(GLenum pname, GLint * data);
-void GLTrace_glGetProgramiv(GLuint program, GLenum pname, GLint * params);
-void GLTrace_glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
-void GLTrace_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetShaderiv(GLuint shader, GLenum pname, GLint * params);
-void GLTrace_glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
-void GLTrace_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision);
-void GLTrace_glGetShaderSource(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source);
-const GLubyte * GLTrace_glGetString(GLenum name);
-void GLTrace_glGetTexParameterfv(GLenum target, GLenum pname, GLfloat * params);
-void GLTrace_glGetTexParameteriv(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetUniformfv(GLuint program, GLint location, GLfloat * params);
-void GLTrace_glGetUniformiv(GLuint program, GLint location, GLint * params);
-GLint GLTrace_glGetUniformLocation(GLuint program, const GLchar * name);
-void GLTrace_glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat * params);
-void GLTrace_glGetVertexAttribiv(GLuint index, GLenum pname, GLint * params);
-void GLTrace_glGetVertexAttribPointerv(GLuint index, GLenum pname, void ** pointer);
-void GLTrace_glHint(GLenum target, GLenum mode);
-GLboolean GLTrace_glIsBuffer(GLuint buffer);
-GLboolean GLTrace_glIsEnabled(GLenum cap);
-GLboolean GLTrace_glIsFramebuffer(GLuint framebuffer);
-GLboolean GLTrace_glIsProgram(GLuint program);
-GLboolean GLTrace_glIsRenderbuffer(GLuint renderbuffer);
-GLboolean GLTrace_glIsShader(GLuint shader);
-GLboolean GLTrace_glIsTexture(GLuint texture);
-void GLTrace_glLineWidth(GLfloat width);
-void GLTrace_glLinkProgram(GLuint program);
-void GLTrace_glPixelStorei(GLenum pname, GLint param);
-void GLTrace_glPolygonOffset(GLfloat factor, GLfloat units);
-void GLTrace_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels);
-void GLTrace_glReleaseShaderCompiler(void);
-void GLTrace_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glSampleCoverage(GLfloat value, GLboolean invert);
-void GLTrace_glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
-void GLTrace_glShaderBinary(GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length);
-void GLTrace_glShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length);
-void GLTrace_glStencilFunc(GLenum func, GLint ref, GLuint mask);
-void GLTrace_glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
-void GLTrace_glStencilMask(GLuint mask);
-void GLTrace_glStencilMaskSeparate(GLenum face, GLuint mask);
-void GLTrace_glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);
-void GLTrace_glStencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
-void GLTrace_glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels);
-void GLTrace_glTexParameterf(GLenum target, GLenum pname, GLfloat param);
-void GLTrace_glTexParameterfv(GLenum target, GLenum pname, const GLfloat * params);
-void GLTrace_glTexParameteri(GLenum target, GLenum pname, GLint param);
-void GLTrace_glTexParameteriv(GLenum target, GLenum pname, const GLint * params);
-void GLTrace_glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels);
-void GLTrace_glUniform1f(GLint location, GLfloat v0);
-void GLTrace_glUniform1fv(GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glUniform1i(GLint location, GLint v0);
-void GLTrace_glUniform1iv(GLint location, GLsizei count, const GLint * value);
-void GLTrace_glUniform2f(GLint location, GLfloat v0, GLfloat v1);
-void GLTrace_glUniform2fv(GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glUniform2i(GLint location, GLint v0, GLint v1);
-void GLTrace_glUniform2iv(GLint location, GLsizei count, const GLint * value);
-void GLTrace_glUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-void GLTrace_glUniform3fv(GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glUniform3i(GLint location, GLint v0, GLint v1, GLint v2);
-void GLTrace_glUniform3iv(GLint location, GLsizei count, const GLint * value);
-void GLTrace_glUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-void GLTrace_glUniform4fv(GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glUniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-void GLTrace_glUniform4iv(GLint location, GLsizei count, const GLint * value);
-void GLTrace_glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUseProgram(GLuint program);
-void GLTrace_glValidateProgram(GLuint program);
-void GLTrace_glVertexAttrib1f(GLuint index, GLfloat x);
-void GLTrace_glVertexAttrib1fv(GLuint index, const GLfloat * v);
-void GLTrace_glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y);
-void GLTrace_glVertexAttrib2fv(GLuint index, const GLfloat * v);
-void GLTrace_glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
-void GLTrace_glVertexAttrib3fv(GLuint index, const GLfloat * v);
-void GLTrace_glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void GLTrace_glVertexAttrib4fv(GLuint index, const GLfloat * v);
-void GLTrace_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer);
-void GLTrace_glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
-void GLTrace_glReadBuffer(GLenum mode);
-void GLTrace_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices);
-void GLTrace_glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
-void GLTrace_glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
-void GLTrace_glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-void GLTrace_glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
-void GLTrace_glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
-void GLTrace_glGenQueries(GLsizei n, GLuint * ids);
-void GLTrace_glDeleteQueries(GLsizei n, const GLuint * ids);
-GLboolean GLTrace_glIsQuery(GLuint id);
-void GLTrace_glBeginQuery(GLenum target, GLuint id);
-void GLTrace_glEndQuery(GLenum target);
-void GLTrace_glGetQueryiv(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint * params);
-GLboolean GLTrace_glUnmapBuffer(GLenum target);
-void GLTrace_glGetBufferPointerv(GLenum target, GLenum pname, void ** params);
-void GLTrace_glDrawBuffers(GLsizei n, const GLenum * bufs);
-void GLTrace_glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-void GLTrace_glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
-void * GLTrace_glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-void GLTrace_glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
-void GLTrace_glBindVertexArray(GLuint array);
-void GLTrace_glDeleteVertexArrays(GLsizei n, const GLuint * arrays);
-void GLTrace_glGenVertexArrays(GLsizei n, GLuint * arrays);
-GLboolean GLTrace_glIsVertexArray(GLuint array);
-void GLTrace_glGetIntegeri_v(GLenum target, GLuint index, GLint * data);
-void GLTrace_glBeginTransformFeedback(GLenum primitiveMode);
-void GLTrace_glEndTransformFeedback(void);
-void GLTrace_glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
-void GLTrace_glBindBufferBase(GLenum target, GLuint index, GLuint buffer);
-void GLTrace_glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode);
-void GLTrace_glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name);
-void GLTrace_glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer);
-void GLTrace_glGetVertexAttribIiv(GLuint index, GLenum pname, GLint * params);
-void GLTrace_glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint * params);
-void GLTrace_glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
-void GLTrace_glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
-void GLTrace_glVertexAttribI4iv(GLuint index, const GLint * v);
-void GLTrace_glVertexAttribI4uiv(GLuint index, const GLuint * v);
-void GLTrace_glGetUniformuiv(GLuint program, GLint location, GLuint * params);
-GLint GLTrace_glGetFragDataLocation(GLuint program, const GLchar * name);
-void GLTrace_glUniform1ui(GLint location, GLuint v0);
-void GLTrace_glUniform2ui(GLint location, GLuint v0, GLuint v1);
-void GLTrace_glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
-void GLTrace_glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-void GLTrace_glUniform1uiv(GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glUniform2uiv(GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glUniform3uiv(GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glUniform4uiv(GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * value);
-void GLTrace_glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint * value);
-void GLTrace_glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat * value);
-void GLTrace_glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
-const GLubyte * GLTrace_glGetStringi(GLenum name, GLuint index);
-void GLTrace_glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
-void GLTrace_glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices);
-void GLTrace_glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params);
-GLuint GLTrace_glGetUniformBlockIndex(GLuint program, const GLchar * uniformBlockName);
-void GLTrace_glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params);
-void GLTrace_glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName);
-void GLTrace_glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
-void GLTrace_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount);
-void GLTrace_glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount);
-GLsync GLTrace_glFenceSync(GLenum condition, GLbitfield flags);
-GLboolean GLTrace_glIsSync(GLsync sync);
-void GLTrace_glDeleteSync(GLsync sync);
-GLenum GLTrace_glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
-void GLTrace_glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
-void GLTrace_glGetInteger64v(GLenum pname, GLint64 * data);
-void GLTrace_glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values);
-void GLTrace_glGetInteger64i_v(GLenum target, GLuint index, GLint64 * data);
-void GLTrace_glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64 * params);
-void GLTrace_glGenSamplers(GLsizei count, GLuint * samplers);
-void GLTrace_glDeleteSamplers(GLsizei count, const GLuint * samplers);
-GLboolean GLTrace_glIsSampler(GLuint sampler);
-void GLTrace_glBindSampler(GLuint unit, GLuint sampler);
-void GLTrace_glSamplerParameteri(GLuint sampler, GLenum pname, GLint param);
-void GLTrace_glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint * param);
-void GLTrace_glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
-void GLTrace_glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * param);
-void GLTrace_glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint * params);
-void GLTrace_glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat * params);
-void GLTrace_glVertexAttribDivisor(GLuint index, GLuint divisor);
-void GLTrace_glBindTransformFeedback(GLenum target, GLuint id);
-void GLTrace_glDeleteTransformFeedbacks(GLsizei n, const GLuint * ids);
-void GLTrace_glGenTransformFeedbacks(GLsizei n, GLuint * ids);
-GLboolean GLTrace_glIsTransformFeedback(GLuint id);
-void GLTrace_glPauseTransformFeedback(void);
-void GLTrace_glResumeTransformFeedback(void);
-void GLTrace_glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary);
-void GLTrace_glProgramBinary(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length);
-void GLTrace_glProgramParameteri(GLuint program, GLenum pname, GLint value);
-void GLTrace_glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum * attachments);
-void GLTrace_glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height);
-void GLTrace_glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-void GLTrace_glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params);
-void GLTrace_glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
-void GLTrace_glDispatchComputeIndirect(GLintptr indirect);
-void GLTrace_glDrawArraysIndirect(GLenum mode, const void * indirect);
-void GLTrace_glDrawElementsIndirect(GLenum mode, GLenum type, const void * indirect);
-void GLTrace_glFramebufferParameteri(GLenum target, GLenum pname, GLint param);
-void GLTrace_glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetProgramInterfaceiv(GLuint program, GLenum programInterface, GLenum pname, GLint * params);
-GLuint GLTrace_glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar * name);
-void GLTrace_glGetProgramResourceName(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name);
-void GLTrace_glGetProgramResourceiv(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params);
-GLint GLTrace_glGetProgramResourceLocation(GLuint program, GLenum programInterface, const GLchar * name);
-void GLTrace_glUseProgramStages(GLuint pipeline, GLbitfield stages, GLuint program);
-void GLTrace_glActiveShaderProgram(GLuint pipeline, GLuint program);
-GLuint GLTrace_glCreateShaderProgramv(GLenum type, GLsizei count, const GLchar *const* strings);
-void GLTrace_glBindProgramPipeline(GLuint pipeline);
-void GLTrace_glDeleteProgramPipelines(GLsizei n, const GLuint * pipelines);
-void GLTrace_glGenProgramPipelines(GLsizei n, GLuint * pipelines);
-GLboolean GLTrace_glIsProgramPipeline(GLuint pipeline);
-void GLTrace_glGetProgramPipelineiv(GLuint pipeline, GLenum pname, GLint * params);
-void GLTrace_glProgramUniform1i(GLuint program, GLint location, GLint v0);
-void GLTrace_glProgramUniform2i(GLuint program, GLint location, GLint v0, GLint v1);
-void GLTrace_glProgramUniform3i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
-void GLTrace_glProgramUniform4i(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-void GLTrace_glProgramUniform1ui(GLuint program, GLint location, GLuint v0);
-void GLTrace_glProgramUniform2ui(GLuint program, GLint location, GLuint v0, GLuint v1);
-void GLTrace_glProgramUniform3ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
-void GLTrace_glProgramUniform4ui(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-void GLTrace_glProgramUniform1f(GLuint program, GLint location, GLfloat v0);
-void GLTrace_glProgramUniform2f(GLuint program, GLint location, GLfloat v0, GLfloat v1);
-void GLTrace_glProgramUniform3f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-void GLTrace_glProgramUniform4f(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-void GLTrace_glProgramUniform1iv(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform2iv(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform3iv(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform4iv(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform1uiv(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform2uiv(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform3uiv(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform4uiv(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform1fv(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform2fv(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform3fv(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform4fv(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix2x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix3x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix2x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix4x2fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix3x4fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix4x3fv(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glValidateProgramPipeline(GLuint pipeline);
-void GLTrace_glGetProgramPipelineInfoLog(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
-void GLTrace_glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
-void GLTrace_glGetBooleani_v(GLenum target, GLuint index, GLboolean * data);
-void GLTrace_glMemoryBarrier(GLbitfield barriers);
-void GLTrace_glMemoryBarrierByRegion(GLbitfield barriers);
-void GLTrace_glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
-void GLTrace_glGetMultisamplefv(GLenum pname, GLuint index, GLfloat * val);
-void GLTrace_glSampleMaski(GLuint maskNumber, GLbitfield mask);
-void GLTrace_glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint * params);
-void GLTrace_glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat * params);
-void GLTrace_glBindVertexBuffer(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride);
-void GLTrace_glVertexAttribFormat(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset);
-void GLTrace_glVertexAttribIFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset);
-void GLTrace_glVertexAttribBinding(GLuint attribindex, GLuint bindingindex);
-void GLTrace_glVertexBindingDivisor(GLuint bindingindex, GLuint divisor);
-
-// Declarations for GL2Ext APIs
-
-void GLTrace_glBlendBarrierKHR(void);
-void GLTrace_glDebugMessageControlKHR(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled);
-void GLTrace_glDebugMessageInsertKHR(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf);
-void GLTrace_glDebugMessageCallbackKHR(GLDEBUGPROCKHR callback, const void * userParam);
-GLuint GLTrace_glGetDebugMessageLogKHR(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog);
-void GLTrace_glPushDebugGroupKHR(GLenum source, GLuint id, GLsizei length, const GLchar * message);
-void GLTrace_glPopDebugGroupKHR(void);
-void GLTrace_glObjectLabelKHR(GLenum identifier, GLuint name, GLsizei length, const GLchar * label);
-void GLTrace_glGetObjectLabelKHR(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label);
-void GLTrace_glObjectPtrLabelKHR(const void * ptr, GLsizei length, const GLchar * label);
-void GLTrace_glGetObjectPtrLabelKHR(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label);
-void GLTrace_glGetPointervKHR(GLenum pname, void ** params);
-void GLTrace_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image);
-void GLTrace_glEGLImageTargetRenderbufferStorageOES(GLenum target, GLeglImageOES image);
-void GLTrace_glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary);
-void GLTrace_glProgramBinaryOES(GLuint program, GLenum binaryFormat, const void * binary, GLint length);
-void * GLTrace_glMapBufferOES(GLenum target, GLenum access);
-GLboolean GLTrace_glUnmapBufferOES(GLenum target);
-void GLTrace_glGetBufferPointervOES(GLenum target, GLenum pname, void ** params);
-void GLTrace_glMinSampleShadingOES(GLfloat value);
-void GLTrace_glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels);
-void GLTrace_glTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels);
-void GLTrace_glCopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-void GLTrace_glCompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data);
-void GLTrace_glCompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data);
-void GLTrace_glFramebufferTexture3DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
-void GLTrace_glTexStorage3DMultisampleOES(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
-void GLTrace_glBindVertexArrayOES(GLuint array);
-void GLTrace_glDeleteVertexArraysOES(GLsizei n, const GLuint * arrays);
-void GLTrace_glGenVertexArraysOES(GLsizei n, GLuint * arrays);
-GLboolean GLTrace_glIsVertexArrayOES(GLuint array);
-void GLTrace_glGetPerfMonitorGroupsAMD(GLint * numGroups, GLsizei groupsSize, GLuint * groups);
-void GLTrace_glGetPerfMonitorCountersAMD(GLuint group, GLint * numCounters, GLint * maxActiveCounters, GLsizei counterSize, GLuint * counters);
-void GLTrace_glGetPerfMonitorGroupStringAMD(GLuint group, GLsizei bufSize, GLsizei * length, GLchar * groupString);
-void GLTrace_glGetPerfMonitorCounterStringAMD(GLuint group, GLuint counter, GLsizei bufSize, GLsizei * length, GLchar * counterString);
-void GLTrace_glGetPerfMonitorCounterInfoAMD(GLuint group, GLuint counter, GLenum pname, void * data);
-void GLTrace_glGenPerfMonitorsAMD(GLsizei n, GLuint * monitors);
-void GLTrace_glDeletePerfMonitorsAMD(GLsizei n, GLuint * monitors);
-void GLTrace_glSelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint * counterList);
-void GLTrace_glBeginPerfMonitorAMD(GLuint monitor);
-void GLTrace_glEndPerfMonitorAMD(GLuint monitor);
-void GLTrace_glGetPerfMonitorCounterDataAMD(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint * data, GLint * bytesWritten);
-void GLTrace_glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-void GLTrace_glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-void GLTrace_glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
-void GLTrace_glVertexAttribDivisorANGLE(GLuint index, GLuint divisor);
-void GLTrace_glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei * length, GLchar * source);
-void GLTrace_glCopyTextureLevelsAPPLE(GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount);
-void GLTrace_glRenderbufferStorageMultisampleAPPLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glResolveMultisampleFramebufferAPPLE(void);
-GLsync GLTrace_glFenceSyncAPPLE(GLenum condition, GLbitfield flags);
-GLboolean GLTrace_glIsSyncAPPLE(GLsync sync);
-void GLTrace_glDeleteSyncAPPLE(GLsync sync);
-GLenum GLTrace_glClientWaitSyncAPPLE(GLsync sync, GLbitfield flags, GLuint64 timeout);
-void GLTrace_glWaitSyncAPPLE(GLsync sync, GLbitfield flags, GLuint64 timeout);
-void GLTrace_glGetInteger64vAPPLE(GLenum pname, GLint64 * params);
-void GLTrace_glGetSyncivAPPLE(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values);
-void GLTrace_glCopyImageSubDataEXT(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
-void GLTrace_glLabelObjectEXT(GLenum type, GLuint object, GLsizei length, const GLchar * label);
-void GLTrace_glGetObjectLabelEXT(GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label);
-void GLTrace_glInsertEventMarkerEXT(GLsizei length, const GLchar * marker);
-void GLTrace_glPushGroupMarkerEXT(GLsizei length, const GLchar * marker);
-void GLTrace_glPopGroupMarkerEXT(void);
-void GLTrace_glDiscardFramebufferEXT(GLenum target, GLsizei numAttachments, const GLenum * attachments);
-void GLTrace_glGenQueriesEXT(GLsizei n, GLuint * ids);
-void GLTrace_glDeleteQueriesEXT(GLsizei n, const GLuint * ids);
-GLboolean GLTrace_glIsQueryEXT(GLuint id);
-void GLTrace_glBeginQueryEXT(GLenum target, GLuint id);
-void GLTrace_glEndQueryEXT(GLenum target);
-void GLTrace_glQueryCounterEXT(GLuint id, GLenum target);
-void GLTrace_glGetQueryivEXT(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetQueryObjectivEXT(GLuint id, GLenum pname, GLint * params);
-void GLTrace_glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint * params);
-void GLTrace_glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64 * params);
-void GLTrace_glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64 * params);
-void GLTrace_glDrawBuffersEXT(GLsizei n, const GLenum * bufs);
-void GLTrace_glEnableiEXT(GLenum target, GLuint index);
-void GLTrace_glDisableiEXT(GLenum target, GLuint index);
-void GLTrace_glBlendEquationiEXT(GLuint buf, GLenum mode);
-void GLTrace_glBlendEquationSeparateiEXT(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
-void GLTrace_glBlendFunciEXT(GLuint buf, GLenum src, GLenum dst);
-void GLTrace_glBlendFuncSeparateiEXT(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
-void GLTrace_glColorMaskiEXT(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
-GLboolean GLTrace_glIsEnablediEXT(GLenum target, GLuint index);
-void GLTrace_glDrawArraysInstancedEXT(GLenum mode, GLint start, GLsizei count, GLsizei primcount);
-void GLTrace_glDrawElementsInstancedEXT(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
-void GLTrace_glFramebufferTextureEXT(GLenum target, GLenum attachment, GLuint texture, GLint level);
-void GLTrace_glVertexAttribDivisorEXT(GLuint index, GLuint divisor);
-void * GLTrace_glMapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
-void GLTrace_glFlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length);
-void GLTrace_glMultiDrawArraysEXT(GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount);
-void GLTrace_glMultiDrawElementsEXT(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount);
-void GLTrace_glRenderbufferStorageMultisampleEXT(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glFramebufferTexture2DMultisampleEXT(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
-void GLTrace_glReadBufferIndexedEXT(GLenum src, GLint index);
-void GLTrace_glDrawBuffersIndexedEXT(GLint n, const GLenum * location, const GLint * indices);
-void GLTrace_glGetIntegeri_vEXT(GLenum target, GLuint index, GLint * data);
-void GLTrace_glPrimitiveBoundingBoxEXT(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
-GLenum GLTrace_glGetGraphicsResetStatusEXT(void);
-void GLTrace_glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data);
-void GLTrace_glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat * params);
-void GLTrace_glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint * params);
-void GLTrace_glActiveShaderProgramEXT(GLuint pipeline, GLuint program);
-void GLTrace_glBindProgramPipelineEXT(GLuint pipeline);
-GLuint GLTrace_glCreateShaderProgramvEXT(GLenum type, GLsizei count, const GLchar ** strings);
-void GLTrace_glDeleteProgramPipelinesEXT(GLsizei n, const GLuint * pipelines);
-void GLTrace_glGenProgramPipelinesEXT(GLsizei n, GLuint * pipelines);
-void GLTrace_glGetProgramPipelineInfoLogEXT(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog);
-void GLTrace_glGetProgramPipelineivEXT(GLuint pipeline, GLenum pname, GLint * params);
-GLboolean GLTrace_glIsProgramPipelineEXT(GLuint pipeline);
-void GLTrace_glProgramParameteriEXT(GLuint program, GLenum pname, GLint value);
-void GLTrace_glProgramUniform1fEXT(GLuint program, GLint location, GLfloat v0);
-void GLTrace_glProgramUniform1fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform1iEXT(GLuint program, GLint location, GLint v0);
-void GLTrace_glProgramUniform1ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform2fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1);
-void GLTrace_glProgramUniform2fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform2iEXT(GLuint program, GLint location, GLint v0, GLint v1);
-void GLTrace_glProgramUniform2ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform3fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
-void GLTrace_glProgramUniform3fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform3iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint v2);
-void GLTrace_glProgramUniform3ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniform4fEXT(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
-void GLTrace_glProgramUniform4fvEXT(GLuint program, GLint location, GLsizei count, const GLfloat * value);
-void GLTrace_glProgramUniform4iEXT(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3);
-void GLTrace_glProgramUniform4ivEXT(GLuint program, GLint location, GLsizei count, const GLint * value);
-void GLTrace_glProgramUniformMatrix2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUseProgramStagesEXT(GLuint pipeline, GLbitfield stages, GLuint program);
-void GLTrace_glValidateProgramPipelineEXT(GLuint pipeline);
-void GLTrace_glProgramUniform1uiEXT(GLuint program, GLint location, GLuint v0);
-void GLTrace_glProgramUniform2uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1);
-void GLTrace_glProgramUniform3uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2);
-void GLTrace_glProgramUniform4uiEXT(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
-void GLTrace_glProgramUniform1uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform2uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform3uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniform4uivEXT(GLuint program, GLint location, GLsizei count, const GLuint * value);
-void GLTrace_glProgramUniformMatrix2x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix3x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix2x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix4x2fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix3x4fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glProgramUniformMatrix4x3fvEXT(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glPatchParameteriEXT(GLenum pname, GLint value);
-void GLTrace_glTexParameterIivEXT(GLenum target, GLenum pname, const GLint * params);
-void GLTrace_glTexParameterIuivEXT(GLenum target, GLenum pname, const GLuint * params);
-void GLTrace_glGetTexParameterIivEXT(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetTexParameterIuivEXT(GLenum target, GLenum pname, GLuint * params);
-void GLTrace_glSamplerParameterIivEXT(GLuint sampler, GLenum pname, const GLint * param);
-void GLTrace_glSamplerParameterIuivEXT(GLuint sampler, GLenum pname, const GLuint * param);
-void GLTrace_glGetSamplerParameterIivEXT(GLuint sampler, GLenum pname, GLint * params);
-void GLTrace_glGetSamplerParameterIuivEXT(GLuint sampler, GLenum pname, GLuint * params);
-void GLTrace_glTexBufferEXT(GLenum target, GLenum internalformat, GLuint buffer);
-void GLTrace_glTexBufferRangeEXT(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
-void GLTrace_glTexStorage1DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
-void GLTrace_glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glTexStorage3DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-void GLTrace_glTextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width);
-void GLTrace_glTextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glTextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-void GLTrace_glTextureViewEXT(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
-void GLTrace_glRenderbufferStorageMultisampleIMG(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glFramebufferTexture2DMultisampleIMG(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
-void GLTrace_glBeginPerfQueryINTEL(GLuint queryHandle);
-void GLTrace_glCreatePerfQueryINTEL(GLuint queryId, GLuint * queryHandle);
-void GLTrace_glDeletePerfQueryINTEL(GLuint queryHandle);
-void GLTrace_glEndPerfQueryINTEL(GLuint queryHandle);
-void GLTrace_glGetFirstPerfQueryIdINTEL(GLuint * queryId);
-void GLTrace_glGetNextPerfQueryIdINTEL(GLuint queryId, GLuint * nextQueryId);
-void GLTrace_glGetPerfCounterInfoINTEL(GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar * counterName, GLuint counterDescLength, GLchar * counterDesc, GLuint * counterOffset, GLuint * counterDataSize, GLuint * counterTypeEnum, GLuint * counterDataTypeEnum, GLuint64 * rawCounterMaxValue);
-void GLTrace_glGetPerfQueryDataINTEL(GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid * data, GLuint * bytesWritten);
-void GLTrace_glGetPerfQueryIdByNameINTEL(GLchar * queryName, GLuint * queryId);
-void GLTrace_glGetPerfQueryInfoINTEL(GLuint queryId, GLuint queryNameLength, GLchar * queryName, GLuint * dataSize, GLuint * noCounters, GLuint * noInstances, GLuint * capsMask);
-void GLTrace_glBlendParameteriNV(GLenum pname, GLint value);
-void GLTrace_glBlendBarrierNV(void);
-void GLTrace_glCopyBufferSubDataNV(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
-void GLTrace_glCoverageMaskNV(GLboolean mask);
-void GLTrace_glCoverageOperationNV(GLenum operation);
-void GLTrace_glDrawBuffersNV(GLsizei n, const GLenum * bufs);
-void GLTrace_glDrawArraysInstancedNV(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
-void GLTrace_glDrawElementsInstancedNV(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount);
-void GLTrace_glDeleteFencesNV(GLsizei n, const GLuint * fences);
-void GLTrace_glGenFencesNV(GLsizei n, GLuint * fences);
-GLboolean GLTrace_glIsFenceNV(GLuint fence);
-GLboolean GLTrace_glTestFenceNV(GLuint fence);
-void GLTrace_glGetFenceivNV(GLuint fence, GLenum pname, GLint * params);
-void GLTrace_glFinishFenceNV(GLuint fence);
-void GLTrace_glSetFenceNV(GLuint fence, GLenum condition);
-void GLTrace_glBlitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
-void GLTrace_glRenderbufferStorageMultisampleNV(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glVertexAttribDivisorNV(GLuint index, GLuint divisor);
-void GLTrace_glUniformMatrix2x3fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix3x2fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix2x4fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix4x2fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix3x4fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glUniformMatrix4x3fvNV(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
-void GLTrace_glReadBufferNV(GLenum mode);
-void GLTrace_glAlphaFuncQCOM(GLenum func, GLclampf ref);
-void GLTrace_glGetDriverControlsQCOM(GLint * num, GLsizei size, GLuint * driverControls);
-void GLTrace_glGetDriverControlStringQCOM(GLuint driverControl, GLsizei bufSize, GLsizei * length, GLchar * driverControlString);
-void GLTrace_glEnableDriverControlQCOM(GLuint driverControl);
-void GLTrace_glDisableDriverControlQCOM(GLuint driverControl);
-void GLTrace_glExtGetTexturesQCOM(GLuint * textures, GLint maxTextures, GLint * numTextures);
-void GLTrace_glExtGetBuffersQCOM(GLuint * buffers, GLint maxBuffers, GLint * numBuffers);
-void GLTrace_glExtGetRenderbuffersQCOM(GLuint * renderbuffers, GLint maxRenderbuffers, GLint * numRenderbuffers);
-void GLTrace_glExtGetFramebuffersQCOM(GLuint * framebuffers, GLint maxFramebuffers, GLint * numFramebuffers);
-void GLTrace_glExtGetTexLevelParameterivQCOM(GLuint texture, GLenum face, GLint level, GLenum pname, GLint * params);
-void GLTrace_glExtTexObjectStateOverrideiQCOM(GLenum target, GLenum pname, GLint param);
-void GLTrace_glExtGetTexSubImageQCOM(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void * texels);
-void GLTrace_glExtGetBufferPointervQCOM(GLenum target, void ** params);
-void GLTrace_glExtGetShadersQCOM(GLuint * shaders, GLint maxShaders, GLint * numShaders);
-void GLTrace_glExtGetProgramsQCOM(GLuint * programs, GLint maxPrograms, GLint * numPrograms);
-GLboolean GLTrace_glExtIsProgramBinaryQCOM(GLuint program);
-void GLTrace_glExtGetProgramBinarySourceQCOM(GLuint program, GLenum shadertype, GLchar * source, GLint * length);
-void GLTrace_glStartTilingQCOM(GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask);
-void GLTrace_glEndTilingQCOM(GLbitfield preserveMask);
-
-// Declarations for GL1 APIs
-
-void GLTrace_glAlphaFunc(GLenum func, GLfloat ref);
-void GLTrace_glClipPlanef(GLenum p, const GLfloat * eqn);
-void GLTrace_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void GLTrace_glFogf(GLenum pname, GLfloat param);
-void GLTrace_glFogfv(GLenum pname, const GLfloat * params);
-void GLTrace_glFrustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
-void GLTrace_glGetClipPlanef(GLenum plane, GLfloat * equation);
-void GLTrace_glGetLightfv(GLenum light, GLenum pname, GLfloat * params);
-void GLTrace_glGetMaterialfv(GLenum face, GLenum pname, GLfloat * params);
-void GLTrace_glGetTexEnvfv(GLenum target, GLenum pname, GLfloat * params);
-void GLTrace_glLightModelf(GLenum pname, GLfloat param);
-void GLTrace_glLightModelfv(GLenum pname, const GLfloat * params);
-void GLTrace_glLightf(GLenum light, GLenum pname, GLfloat param);
-void GLTrace_glLightfv(GLenum light, GLenum pname, const GLfloat * params);
-void GLTrace_glLoadMatrixf(const GLfloat * m);
-void GLTrace_glMaterialf(GLenum face, GLenum pname, GLfloat param);
-void GLTrace_glMaterialfv(GLenum face, GLenum pname, const GLfloat * params);
-void GLTrace_glMultMatrixf(const GLfloat * m);
-void GLTrace_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-void GLTrace_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
-void GLTrace_glOrthof(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
-void GLTrace_glPointParameterf(GLenum pname, GLfloat param);
-void GLTrace_glPointParameterfv(GLenum pname, const GLfloat * params);
-void GLTrace_glPointSize(GLfloat size);
-void GLTrace_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-void GLTrace_glScalef(GLfloat x, GLfloat y, GLfloat z);
-void GLTrace_glTexEnvf(GLenum target, GLenum pname, GLfloat param);
-void GLTrace_glTexEnvfv(GLenum target, GLenum pname, const GLfloat * params);
-void GLTrace_glTranslatef(GLfloat x, GLfloat y, GLfloat z);
-void GLTrace_glAlphaFuncx(GLenum func, GLfixed ref);
-void GLTrace_glClearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
-void GLTrace_glClearDepthx(GLfixed depth);
-void GLTrace_glClientActiveTexture(GLenum texture);
-void GLTrace_glClipPlanex(GLenum plane, const GLfixed * equation);
-void GLTrace_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-void GLTrace_glColor4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
-void GLTrace_glColorPointer(GLint size, GLenum type, GLsizei stride, const void * pointer);
-void GLTrace_glDepthRangex(GLfixed n, GLfixed f);
-void GLTrace_glDisableClientState(GLenum array);
-void GLTrace_glEnableClientState(GLenum array);
-void GLTrace_glFogx(GLenum pname, GLfixed param);
-void GLTrace_glFogxv(GLenum pname, const GLfixed * param);
-void GLTrace_glFrustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
-void GLTrace_glGetClipPlanex(GLenum plane, GLfixed * equation);
-void GLTrace_glGetFixedv(GLenum pname, GLfixed * params);
-void GLTrace_glGetLightxv(GLenum light, GLenum pname, GLfixed * params);
-void GLTrace_glGetMaterialxv(GLenum face, GLenum pname, GLfixed * params);
-void GLTrace_glGetPointerv(GLenum pname, void ** params);
-void GLTrace_glGetTexEnviv(GLenum target, GLenum pname, GLint * params);
-void GLTrace_glGetTexEnvxv(GLenum target, GLenum pname, GLfixed * params);
-void GLTrace_glGetTexParameterxv(GLenum target, GLenum pname, GLfixed * params);
-void GLTrace_glLightModelx(GLenum pname, GLfixed param);
-void GLTrace_glLightModelxv(GLenum pname, const GLfixed * param);
-void GLTrace_glLightx(GLenum light, GLenum pname, GLfixed param);
-void GLTrace_glLightxv(GLenum light, GLenum pname, const GLfixed * params);
-void GLTrace_glLineWidthx(GLfixed width);
-void GLTrace_glLoadIdentity(void);
-void GLTrace_glLoadMatrixx(const GLfixed * m);
-void GLTrace_glLogicOp(GLenum opcode);
-void GLTrace_glMaterialx(GLenum face, GLenum pname, GLfixed param);
-void GLTrace_glMaterialxv(GLenum face, GLenum pname, const GLfixed * param);
-void GLTrace_glMatrixMode(GLenum mode);
-void GLTrace_glMultMatrixx(const GLfixed * m);
-void GLTrace_glMultiTexCoord4x(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
-void GLTrace_glNormal3x(GLfixed nx, GLfixed ny, GLfixed nz);
-void GLTrace_glNormalPointer(GLenum type, GLsizei stride, const void * pointer);
-void GLTrace_glOrthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
-void GLTrace_glPointParameterx(GLenum pname, GLfixed param);
-void GLTrace_glPointParameterxv(GLenum pname, const GLfixed * params);
-void GLTrace_glPointSizex(GLfixed size);
-void GLTrace_glPolygonOffsetx(GLfixed factor, GLfixed units);
-void GLTrace_glPopMatrix(void);
-void GLTrace_glPushMatrix(void);
-void GLTrace_glRotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-void GLTrace_glSampleCoveragex(GLclampx value, GLboolean invert);
-void GLTrace_glScalex(GLfixed x, GLfixed y, GLfixed z);
-void GLTrace_glShadeModel(GLenum mode);
-void GLTrace_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void * pointer);
-void GLTrace_glTexEnvi(GLenum target, GLenum pname, GLint param);
-void GLTrace_glTexEnvx(GLenum target, GLenum pname, GLfixed param);
-void GLTrace_glTexEnviv(GLenum target, GLenum pname, const GLint * params);
-void GLTrace_glTexEnvxv(GLenum target, GLenum pname, const GLfixed * params);
-void GLTrace_glTexParameterx(GLenum target, GLenum pname, GLfixed param);
-void GLTrace_glTexParameterxv(GLenum target, GLenum pname, const GLfixed * params);
-void GLTrace_glTranslatex(GLfixed x, GLfixed y, GLfixed z);
-void GLTrace_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void * pointer);
-
-// Declarations for GL1Ext APIs
-
-void GLTrace_glBlendEquationSeparateOES(GLenum modeRGB, GLenum modeAlpha);
-void GLTrace_glBlendFuncSeparateOES(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
-void GLTrace_glBlendEquationOES(GLenum mode);
-void GLTrace_glMultiTexCoord1bOES(GLenum texture, GLbyte s);
-void GLTrace_glMultiTexCoord1bvOES(GLenum texture, const GLbyte * coords);
-void GLTrace_glMultiTexCoord2bOES(GLenum texture, GLbyte s, GLbyte t);
-void GLTrace_glMultiTexCoord2bvOES(GLenum texture, const GLbyte * coords);
-void GLTrace_glMultiTexCoord3bOES(GLenum texture, GLbyte s, GLbyte t, GLbyte r);
-void GLTrace_glMultiTexCoord3bvOES(GLenum texture, const GLbyte * coords);
-void GLTrace_glMultiTexCoord4bOES(GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q);
-void GLTrace_glMultiTexCoord4bvOES(GLenum texture, const GLbyte * coords);
-void GLTrace_glTexCoord1bOES(GLbyte s);
-void GLTrace_glTexCoord1bvOES(const GLbyte * coords);
-void GLTrace_glTexCoord2bOES(GLbyte s, GLbyte t);
-void GLTrace_glTexCoord2bvOES(const GLbyte * coords);
-void GLTrace_glTexCoord3bOES(GLbyte s, GLbyte t, GLbyte r);
-void GLTrace_glTexCoord3bvOES(const GLbyte * coords);
-void GLTrace_glTexCoord4bOES(GLbyte s, GLbyte t, GLbyte r, GLbyte q);
-void GLTrace_glTexCoord4bvOES(const GLbyte * coords);
-void GLTrace_glVertex2bOES(GLbyte x);
-void GLTrace_glVertex2bvOES(const GLbyte * coords);
-void GLTrace_glVertex3bOES(GLbyte x, GLbyte y);
-void GLTrace_glVertex3bvOES(const GLbyte * coords);
-void GLTrace_glVertex4bOES(GLbyte x, GLbyte y, GLbyte z);
-void GLTrace_glVertex4bvOES(const GLbyte * coords);
-void GLTrace_glDrawTexsOES(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height);
-void GLTrace_glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height);
-void GLTrace_glDrawTexxOES(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height);
-void GLTrace_glDrawTexsvOES(const GLshort * coords);
-void GLTrace_glDrawTexivOES(const GLint * coords);
-void GLTrace_glDrawTexxvOES(const GLfixed * coords);
-void GLTrace_glDrawTexfOES(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height);
-void GLTrace_glDrawTexfvOES(const GLfloat * coords);
-void GLTrace_glAlphaFuncxOES(GLenum func, GLfixed ref);
-void GLTrace_glClearColorxOES(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
-void GLTrace_glClearDepthxOES(GLfixed depth);
-void GLTrace_glClipPlanexOES(GLenum plane, const GLfixed * equation);
-void GLTrace_glColor4xOES(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha);
-void GLTrace_glDepthRangexOES(GLfixed n, GLfixed f);
-void GLTrace_glFogxOES(GLenum pname, GLfixed param);
-void GLTrace_glFogxvOES(GLenum pname, const GLfixed * param);
-void GLTrace_glFrustumxOES(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
-void GLTrace_glGetClipPlanexOES(GLenum plane, GLfixed * equation);
-void GLTrace_glGetFixedvOES(GLenum pname, GLfixed * params);
-void GLTrace_glGetTexEnvxvOES(GLenum target, GLenum pname, GLfixed * params);
-void GLTrace_glGetTexParameterxvOES(GLenum target, GLenum pname, GLfixed * params);
-void GLTrace_glLightModelxOES(GLenum pname, GLfixed param);
-void GLTrace_glLightModelxvOES(GLenum pname, const GLfixed * param);
-void GLTrace_glLightxOES(GLenum light, GLenum pname, GLfixed param);
-void GLTrace_glLightxvOES(GLenum light, GLenum pname, const GLfixed * params);
-void GLTrace_glLineWidthxOES(GLfixed width);
-void GLTrace_glLoadMatrixxOES(const GLfixed * m);
-void GLTrace_glMaterialxOES(GLenum face, GLenum pname, GLfixed param);
-void GLTrace_glMaterialxvOES(GLenum face, GLenum pname, const GLfixed * param);
-void GLTrace_glMultMatrixxOES(const GLfixed * m);
-void GLTrace_glMultiTexCoord4xOES(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q);
-void GLTrace_glNormal3xOES(GLfixed nx, GLfixed ny, GLfixed nz);
-void GLTrace_glOrthoxOES(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f);
-void GLTrace_glPointParameterxvOES(GLenum pname, const GLfixed * params);
-void GLTrace_glPointSizexOES(GLfixed size);
-void GLTrace_glPolygonOffsetxOES(GLfixed factor, GLfixed units);
-void GLTrace_glRotatexOES(GLfixed angle, GLfixed x, GLfixed y, GLfixed z);
-void GLTrace_glSampleCoverageOES(GLfixed value, GLboolean invert);
-void GLTrace_glScalexOES(GLfixed x, GLfixed y, GLfixed z);
-void GLTrace_glTexEnvxOES(GLenum target, GLenum pname, GLfixed param);
-void GLTrace_glTexEnvxvOES(GLenum target, GLenum pname, const GLfixed * params);
-void GLTrace_glTexParameterxOES(GLenum target, GLenum pname, GLfixed param);
-void GLTrace_glTexParameterxvOES(GLenum target, GLenum pname, const GLfixed * params);
-void GLTrace_glTranslatexOES(GLfixed x, GLfixed y, GLfixed z);
-void GLTrace_glGetLightxvOES(GLenum light, GLenum pname, GLfixed * params);
-void GLTrace_glGetMaterialxvOES(GLenum face, GLenum pname, GLfixed * params);
-void GLTrace_glPointParameterxOES(GLenum pname, GLfixed param);
-void GLTrace_glSampleCoveragexOES(GLclampx value, GLboolean invert);
-void GLTrace_glGetTexGenxvOES(GLenum coord, GLenum pname, GLfixed * params);
-void GLTrace_glTexGenxOES(GLenum coord, GLenum pname, GLfixed param);
-void GLTrace_glTexGenxvOES(GLenum coord, GLenum pname, const GLfixed * params);
-GLboolean GLTrace_glIsRenderbufferOES(GLuint renderbuffer);
-void GLTrace_glBindRenderbufferOES(GLenum target, GLuint renderbuffer);
-void GLTrace_glDeleteRenderbuffersOES(GLsizei n, const GLuint * renderbuffers);
-void GLTrace_glGenRenderbuffersOES(GLsizei n, GLuint * renderbuffers);
-void GLTrace_glRenderbufferStorageOES(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-void GLTrace_glGetRenderbufferParameterivOES(GLenum target, GLenum pname, GLint * params);
-GLboolean GLTrace_glIsFramebufferOES(GLuint framebuffer);
-void GLTrace_glBindFramebufferOES(GLenum target, GLuint framebuffer);
-void GLTrace_glDeleteFramebuffersOES(GLsizei n, const GLuint * framebuffers);
-void GLTrace_glGenFramebuffersOES(GLsizei n, GLuint * framebuffers);
-GLenum GLTrace_glCheckFramebufferStatusOES(GLenum target);
-void GLTrace_glFramebufferRenderbufferOES(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
-void GLTrace_glFramebufferTexture2DOES(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
-void GLTrace_glGetFramebufferAttachmentParameterivOES(GLenum target, GLenum attachment, GLenum pname, GLint * params);
-void GLTrace_glGenerateMipmapOES(GLenum target);
-void GLTrace_glCurrentPaletteMatrixOES(GLuint matrixpaletteindex);
-void GLTrace_glLoadPaletteFromModelViewMatrixOES(void);
-void GLTrace_glMatrixIndexPointerOES(GLint size, GLenum type, GLsizei stride, const void * pointer);
-void GLTrace_glWeightPointerOES(GLint size, GLenum type, GLsizei stride, const void * pointer);
-void GLTrace_glPointSizePointerOES(GLenum type, GLsizei stride, const void * pointer);
-GLbitfield GLTrace_glQueryMatrixxOES(GLfixed * mantissa, GLint * exponent);
-void GLTrace_glClearDepthfOES(GLclampf depth);
-void GLTrace_glClipPlanefOES(GLenum plane, const GLfloat * equation);
-void GLTrace_glDepthRangefOES(GLclampf n, GLclampf f);
-void GLTrace_glFrustumfOES(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
-void GLTrace_glGetClipPlanefOES(GLenum plane, GLfloat * equation);
-void GLTrace_glOrthofOES(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f);
-void GLTrace_glTexGenfOES(GLenum coord, GLenum pname, GLfloat param);
-void GLTrace_glTexGenfvOES(GLenum coord, GLenum pname, const GLfloat * params);
-void GLTrace_glTexGeniOES(GLenum coord, GLenum pname, GLint param);
-void GLTrace_glTexGenivOES(GLenum coord, GLenum pname, const GLint * params);
-void GLTrace_glGetTexGenfvOES(GLenum coord, GLenum pname, GLfloat * params);
-void GLTrace_glGetTexGenivOES(GLenum coord, GLenum pname, GLint * params);
-void GLTrace_glClipPlanefIMG(GLenum p, const GLfloat * eqn);
-void GLTrace_glClipPlanexIMG(GLenum p, const GLfixed * eqn);
-
-}; // namespace gltrace
-}; // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
deleted file mode 100644
index d1b3586..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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 <pthread.h>
-#include <cutils/log.h>
-
-extern "C" {
-#include "liblzf/lzf.h"
-}
-
-#include "gltrace_context.h"
-
-namespace android {
-namespace gltrace {
-
-using ::android::gl_hooks_t;
-
-static pthread_key_t sTLSKey = -1;
-static pthread_once_t sPthreadOnceKey = PTHREAD_ONCE_INIT;
-
-void createTLSKey() {
-    pthread_key_create(&sTLSKey, (void (*)(void*))&releaseContext);
-}
-
-GLTraceContext *getGLTraceContext() {
-    return (GLTraceContext*) pthread_getspecific(sTLSKey);
-}
-
-void setGLTraceContext(GLTraceContext *c) {
-    pthread_setspecific(sTLSKey, c);
-}
-
-void setupTraceContextThreadSpecific(GLTraceContext *context) {
-    pthread_once(&sPthreadOnceKey, createTLSKey);
-    setGLTraceContext(context);
-}
-
-void releaseContext() {
-    GLTraceContext *c = getGLTraceContext();
-    if (c != NULL) {
-        delete c;
-        setGLTraceContext(NULL);
-    }
-}
-
-GLTraceState::GLTraceState(TCPStream *stream) {
-    mTraceContextIds = 0;
-    mStream = stream;
-
-    mCollectFbOnEglSwap = false;
-    mCollectFbOnGlDraw = false;
-    mCollectTextureDataOnGlTexImage = false;
-    pthread_rwlock_init(&mTraceOptionsRwLock, NULL);
-}
-
-GLTraceState::~GLTraceState() {
-    if (mStream) {
-        mStream->closeStream();
-        mStream = NULL;
-    }
-}
-
-TCPStream *GLTraceState::getStream() {
-    return mStream;
-}
-
-void GLTraceState::safeSetValue(bool *ptr, bool value, pthread_rwlock_t *lock) {
-    pthread_rwlock_wrlock(lock);
-    *ptr = value;
-    pthread_rwlock_unlock(lock);
-}
-
-bool GLTraceState::safeGetValue(bool *ptr, pthread_rwlock_t *lock) {
-    pthread_rwlock_rdlock(lock);
-    bool value = *ptr;
-    pthread_rwlock_unlock(lock);
-    return value;
-}
-
-void GLTraceState::setCollectFbOnEglSwap(bool en) {
-    safeSetValue(&mCollectFbOnEglSwap, en, &mTraceOptionsRwLock);
-}
-
-void GLTraceState::setCollectFbOnGlDraw(bool en) {
-    safeSetValue(&mCollectFbOnGlDraw, en, &mTraceOptionsRwLock);
-}
-
-void GLTraceState::setCollectTextureDataOnGlTexImage(bool en) {
-    safeSetValue(&mCollectTextureDataOnGlTexImage, en, &mTraceOptionsRwLock);
-}
-
-bool GLTraceState::shouldCollectFbOnEglSwap() {
-    return safeGetValue(&mCollectFbOnEglSwap, &mTraceOptionsRwLock);
-}
-
-bool GLTraceState::shouldCollectFbOnGlDraw() {
-    return safeGetValue(&mCollectFbOnGlDraw, &mTraceOptionsRwLock);
-}
-
-bool GLTraceState::shouldCollectTextureDataOnGlTexImage() {
-    return safeGetValue(&mCollectTextureDataOnGlTexImage, &mTraceOptionsRwLock);
-}
-
-GLTraceContext *GLTraceState::createTraceContext(int version, EGLContext eglContext) {
-    int id = __sync_fetch_and_add(&mTraceContextIds, 1);
-
-    const size_t DEFAULT_BUFFER_SIZE = 8192;
-    BufferedOutputStream *stream = new BufferedOutputStream(mStream, DEFAULT_BUFFER_SIZE);
-    GLTraceContext *traceContext = new GLTraceContext(id, version, this, stream);
-    mPerContextState[eglContext] = traceContext;
-
-    return traceContext;
-}
-
-GLTraceContext *GLTraceState::getTraceContext(EGLContext c) {
-    return mPerContextState[c];
-}
-
-GLTraceContext::GLTraceContext(int id, int version, GLTraceState *state,
-        BufferedOutputStream *stream) :
-    mId(id),
-    mVersion(version),
-    mVersionMajor(0),
-    mVersionMinor(0),
-    mVersionParsed(false),
-    mState(state),
-    mBufferedOutputStream(stream),
-    mElementArrayBuffers(DefaultKeyedVector<GLuint, ElementArrayBuffer*>(NULL))
-{
-    fbcontents = fbcompressed = NULL;
-    fbcontentsSize = 0;
-}
-
-int GLTraceContext::getId() {
-    return mId;
-}
-
-int GLTraceContext::getVersion() {
-    return mVersion;
-}
-
-int GLTraceContext::getVersionMajor() {
-    if (!mVersionParsed) {
-        parseGlesVersion();
-        mVersionParsed = true;
-    }
-    return mVersionMajor;
-}
-
-int GLTraceContext::getVersionMinor() {
-    if (!mVersionParsed) {
-        parseGlesVersion();
-        mVersionParsed = true;
-    }
-    return mVersionMinor;
-}
-
-GLTraceState *GLTraceContext::getGlobalTraceState() {
-    return mState;
-}
-
-void GLTraceContext::parseGlesVersion() {
-    const char* str = (const char*)hooks->gl.glGetString(GL_VERSION);
-    int major, minor;
-    if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
-        if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
-            ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
-            major = 1;
-            minor = 0;
-        }
-    }
-    mVersionMajor = major;
-    mVersionMinor = minor;
-}
-
-void GLTraceContext::resizeFBMemory(unsigned minSize) {
-    if (fbcontentsSize >= minSize) {
-        return;
-    }
-
-    if (fbcontents != NULL) {
-        free(fbcontents);
-        free(fbcompressed);
-    }
-
-    fbcontents = malloc(minSize);
-    fbcompressed = malloc(minSize);
-
-    fbcontentsSize = minSize;
-}
-
-/** obtain a pointer to the compressed framebuffer image */
-void GLTraceContext::getCompressedFB(void **fb, unsigned *fbsize, unsigned *fbwidth, 
-                            unsigned *fbheight, FBBinding fbToRead) {
-    int viewport[4] = {};
-    hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
-    unsigned fbContentsSize = viewport[2] * viewport[3] * 4;
-
-    resizeFBMemory(fbContentsSize);
-
-    // switch current framebuffer binding if necessary
-    GLint currentFb = -1;
-    bool fbSwitched = false;
-    if (fbToRead != CURRENTLY_BOUND_FB) {
-        hooks->gl.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFb);
-
-        if (currentFb != 0) {
-            hooks->gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
-            fbSwitched = true;
-        }
-    }
-
-    hooks->gl.glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
-                                        GL_RGBA, GL_UNSIGNED_BYTE, fbcontents);
-
-    // switch back to previously bound buffer if necessary
-    if (fbSwitched) {
-        hooks->gl.glBindFramebuffer(GL_FRAMEBUFFER, currentFb);
-    }
-
-    *fbsize = lzf_compress(fbcontents, fbContentsSize, fbcompressed, fbContentsSize);
-    *fb = fbcompressed;
-    *fbwidth = viewport[2];
-    *fbheight = viewport[3];
-}
-
-void GLTraceContext::traceGLMessage(GLMessage *msg) {
-    mBufferedOutputStream->send(msg);
-
-    GLMessage_Function func = msg->function();
-    if (func == GLMessage::eglSwapBuffers
-        || func == GLMessage::eglCreateContext
-        || func == GLMessage::eglMakeCurrent
-        || func == GLMessage::glDrawArrays
-        || func == GLMessage::glDrawElements) {
-        mBufferedOutputStream->flush();
-    }
-}
-
-void GLTraceContext::bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size) {
-    // free previously bound buffer if any
-    ElementArrayBuffer *oldBuffer = mElementArrayBuffers.valueFor(bufferId);
-    if (oldBuffer != NULL) {
-        delete oldBuffer;
-    }
-
-    mElementArrayBuffers.add(bufferId, new ElementArrayBuffer(data, size));
-}
-
-void GLTraceContext::getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size) {
-    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
-    if (buffer == NULL) {
-        *data = NULL;
-        *size = 0;
-    } else {
-        *data = buffer->getBuffer();
-        *size = buffer->getSize();
-    }
-}
-
-void GLTraceContext::updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data,
-                                                            GLsizeiptr size) {
-    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
-    if (buffer != NULL) {
-        buffer->updateSubBuffer(offset, data, size);
-    }
-}
-
-void GLTraceContext::deleteBuffer(GLuint bufferId) {
-    ElementArrayBuffer *buffer = mElementArrayBuffers.valueFor(bufferId);
-    if (buffer != NULL) {
-        delete buffer;
-        mElementArrayBuffers.removeItem(bufferId);
-    }
-}
-
-ElementArrayBuffer::ElementArrayBuffer(GLvoid *buf, GLsizeiptr size) {
-    mBuf = malloc(size);
-    mSize = size;
-
-    if (buf != NULL) {
-        memcpy(mBuf, buf, size);
-    }
-}
-
-ElementArrayBuffer::~ElementArrayBuffer() {
-    if (mBuf != NULL) {
-        free(mBuf);
-        mSize = 0;
-    }
-
-    mBuf = NULL;
-}
-
-void ElementArrayBuffer::updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size) {
-    if (offset + size <= mSize) {
-        memcpy((char*)mBuf + offset, data, size);
-    }
-}
-
-GLvoid *ElementArrayBuffer::getBuffer() {
-    return mBuf;
-}
-
-GLsizeiptr ElementArrayBuffer::getSize() {
-    return mSize;
-}
-
-}; // namespace gltrace
-}; // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.h b/opengl/libs/GLES_trace/src/gltrace_context.h
deleted file mode 100644
index 38c7315..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_context.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef __GLTRACE_CONTEXT_H_
-#define __GLTRACE_CONTEXT_H_
-
-#include <map>
-#include <pthread.h>
-#include <utils/KeyedVector.h>
-
-#include "hooks.h"
-#include "gltrace_transport.h"
-
-namespace android {
-namespace gltrace {
-
-using ::android::gl_hooks_t;
-
-enum FBBinding {CURRENTLY_BOUND_FB, FB0};
-
-class GLTraceState;
-
-class ElementArrayBuffer {
-    GLvoid *mBuf;
-    GLsizeiptr mSize;
-
-public:
-    ElementArrayBuffer():mBuf(NULL), mSize(0) {}
-    ElementArrayBuffer(GLvoid *buf, GLsizeiptr size);
-    ~ElementArrayBuffer();
-
-    void updateSubBuffer(GLintptr offset, const GLvoid* data, GLsizeiptr size);
-    GLvoid *getBuffer();
-    GLsizeiptr getSize();
-};
-
-/** GL Trace Context info associated with each EGLContext */
-class GLTraceContext {
-    int mId;                    /* unique context id */
-    int mVersion;               /* GL version, e.g: egl_connection_t::GLESv2_INDEX */
-    int mVersionMajor;          /* GL major version. Lazily parsed in getVersionX(). */
-    int mVersionMinor;          /* GL minor version. Lazily parsed in getVersionX(). */
-    bool mVersionParsed;        /* True if major and minor versions have been parsed. */
-    GLTraceState *mState;       /* parent GL Trace state (for per process GL Trace State Info) */
-
-    void *fbcontents;           /* memory area to read framebuffer contents */
-    void *fbcompressed;         /* destination for lzf compressed framebuffer */
-    unsigned fbcontentsSize;    /* size of fbcontents & fbcompressed buffers */
-
-    BufferedOutputStream *mBufferedOutputStream; /* stream where trace info is sent */
-
-    /* list of element array buffers in use. */
-    DefaultKeyedVector<GLuint, ElementArrayBuffer*> mElementArrayBuffers;
-
-    /* Parses the GL version string returned from glGetString(GL_VERSION) to get find the major and
-       minor versions of the GLES API. The context must be current before calling. */
-    void parseGlesVersion();
-    void resizeFBMemory(unsigned minSize);
-public:
-    gl_hooks_t *hooks;
-
-    GLTraceContext(int id, int version, GLTraceState *state, BufferedOutputStream *stream);
-    int getId();
-    int getVersion();
-    int getVersionMajor();
-    int getVersionMinor();
-    GLTraceState *getGlobalTraceState();
-    void getCompressedFB(void **fb, unsigned *fbsize,
-                            unsigned *fbwidth, unsigned *fbheight,
-                            FBBinding fbToRead);
-
-    // Methods to work with element array buffers
-    void bindBuffer(GLuint bufferId, GLvoid *data, GLsizeiptr size);
-    void getBuffer(GLuint bufferId, GLvoid **data, GLsizeiptr *size);
-    void updateBufferSubData(GLuint bufferId, GLintptr offset, GLvoid *data, GLsizeiptr size);
-    void deleteBuffer(GLuint bufferId);
-
-    void traceGLMessage(GLMessage *msg);
-};
-
-/** Per process trace state. */
-class GLTraceState {
-    int mTraceContextIds;
-    TCPStream *mStream;
-    std::map<EGLContext, GLTraceContext*> mPerContextState;
-
-    /* Options controlling additional data to be collected on
-       certain trace calls. */
-    bool mCollectFbOnEglSwap;
-    bool mCollectFbOnGlDraw;
-    bool mCollectTextureDataOnGlTexImage;
-    pthread_rwlock_t mTraceOptionsRwLock;
-
-    /* helper methods to get/set values using provided lock for mutual exclusion. */
-    void safeSetValue(bool *ptr, bool value, pthread_rwlock_t *lock);
-    bool safeGetValue(bool *ptr, pthread_rwlock_t *lock);
-public:
-    GLTraceState(TCPStream *stream);
-    ~GLTraceState();
-
-    GLTraceContext *createTraceContext(int version, EGLContext c);
-    GLTraceContext *getTraceContext(EGLContext c);
-
-    TCPStream *getStream();
-
-    /* Methods to set trace options. */
-    void setCollectFbOnEglSwap(bool en);
-    void setCollectFbOnGlDraw(bool en);
-    void setCollectTextureDataOnGlTexImage(bool en);
-
-    /* Methods to retrieve trace options. */
-    bool shouldCollectFbOnEglSwap();
-    bool shouldCollectFbOnGlDraw();
-    bool shouldCollectTextureDataOnGlTexImage();
-};
-
-void setupTraceContextThreadSpecific(GLTraceContext *context);
-GLTraceContext *getGLTraceContext();
-void releaseContext();
-
-};
-};
-
-#endif
diff --git a/opengl/libs/GLES_trace/src/gltrace_egl.cpp b/opengl/libs/GLES_trace/src/gltrace_egl.cpp
deleted file mode 100644
index a7878f2..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_egl.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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 <cutils/log.h>
-#include <utils/Timers.h>
-
-#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
-#include "gltrace_context.h"
-#include "gltrace_fixup.h"
-#include "gltrace_transport.h"
-
-namespace android {
-namespace gltrace {
-
-void GLTrace_eglCreateContext(int version, int contextId) {
-    GLMessage glmessage;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmessage.set_context_id(contextId);
-    glmessage.set_function(GLMessage::eglCreateContext);
-
-    // copy argument version
-    GLMessage_DataType *arg_version = glmessage.add_args();
-    arg_version->set_isarray(false);
-    arg_version->set_type(GLMessage::DataType::INT);
-    arg_version->add_intvalue(version);
-
-    // copy argument context
-    GLMessage_DataType *arg_context = glmessage.add_args();
-    arg_context->set_isarray(false);
-    arg_context->set_type(GLMessage::DataType::INT);
-    arg_context->add_intvalue(contextId);
-
-    // set start time and duration
-    glmessage.set_start_time(systemTime());
-    glmessage.set_duration(0);
-
-    glContext->traceGLMessage(&glmessage);
-}
-
-void GLTrace_eglMakeCurrent(int contextId) {
-    GLMessage glmessage;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmessage.set_context_id(contextId);
-    glmessage.set_function(GLMessage::eglMakeCurrent);
-
-    // copy argument context
-    GLMessage_DataType *arg_context = glmessage.add_args();
-    arg_context->set_isarray(false);
-    arg_context->set_type(GLMessage::DataType::INT);
-    arg_context->add_intvalue(contextId);
-
-    // set start time and duration
-    glmessage.set_start_time(systemTime());
-    glmessage.set_duration(0);
-
-    glContext->traceGLMessage(&glmessage);
-}
-
-void GLTrace_eglSwapBuffers(void* /*dpy*/, void* /*draw*/) {
-    GLMessage glmessage;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmessage.set_context_id(glContext->getId());
-    glmessage.set_function(GLMessage::eglSwapBuffers);
-
-    if (glContext->getGlobalTraceState()->shouldCollectFbOnEglSwap()) {
-        // read FB0 since that is what is displayed on the screen
-        fixup_addFBContents(glContext, &glmessage, FB0);
-    }
-
-    // set start time and duration
-    glmessage.set_start_time(systemTime());
-    glmessage.set_duration(0);
-
-    glContext->traceGLMessage(&glmessage);
-}
-
-};
-};
diff --git a/opengl/libs/GLES_trace/src/gltrace_egl.h b/opengl/libs/GLES_trace/src/gltrace_egl.h
deleted file mode 100644
index f4684c5..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_egl.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef __GLTRACE_EGL_H_
-#define __GLTRACE_EGL_H_
-
-namespace android {
-namespace gltrace {
-
-void GLTrace_eglCreateContext(int version, int contextId);
-void GLTrace_eglMakeCurrent(int contextId);
-void GLTrace_eglSwapBuffers(void *dpy, void *draw);
-
-};
-};
-
-#endif
diff --git a/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp b/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp
deleted file mode 100644
index 512d562..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_eglapi.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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 <arpa/inet.h>
-#include <stdlib.h>
-#include <cutils/log.h>
-#include <cutils/properties.h>
-
-#include "hooks.h"
-#include "glestrace.h"
-
-#include "gltrace_context.h"
-#include "gltrace_egl.h"
-#include "gltrace_hooks.h"
-#include "gltrace_transport.h"
-
-namespace android {
-
-using gltrace::GLTraceState;
-using gltrace::GLTraceContext;
-using gltrace::TCPStream;
-
-static pthread_mutex_t sGlTraceStateLock = PTHREAD_MUTEX_INITIALIZER;
-
-static int sGlTraceInProgress;
-static GLTraceState *sGLTraceState;
-static pthread_t sReceiveThreadId;
-
-/**
- * Task that monitors the control stream from the host and updates
- * the trace status according to commands received from the host.
- */
-static void *commandReceiveTask(void *arg) {
-    GLTraceState *state = (GLTraceState *)arg;
-    TCPStream *stream = state->getStream();
-
-    // The control stream always receives an integer size of the
-    // command buffer, followed by the actual command buffer.
-    uint32_t cmdSize;
-
-    // Command Buffer
-    void *cmdBuf = NULL;
-    uint32_t cmdBufSize = 0;
-
-    enum TraceSettingsMasks {
-        READ_FB_ON_EGLSWAP_MASK = 1 << 0,
-        READ_FB_ON_GLDRAW_MASK = 1 << 1,
-        READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK = 1 << 2,
-    };
-
-    while (true) {
-        // read command size
-        if (stream->receive(&cmdSize, sizeof(uint32_t)) < 0) {
-            break;
-        }
-        cmdSize = ntohl(cmdSize);
-
-        // ensure command buffer is of required size
-        if (cmdBufSize < cmdSize) {
-            free(cmdBuf);
-            cmdBufSize = cmdSize;
-            cmdBuf = malloc(cmdSize);
-            if (cmdBuf == NULL)
-                break;
-        }
-
-        // receive the command
-        if (stream->receive(cmdBuf, cmdSize) < 0) {
-            break;
-        }
-
-        if (cmdSize != sizeof(uint32_t)) {
-            // Currently, we only support commands that are a single integer,
-            // so we skip all other commands
-            continue;
-        }
-
-        uint32_t cmd = ntohl(*(uint32_t*)cmdBuf);
-
-        bool collectFbOnEglSwap = (cmd & READ_FB_ON_EGLSWAP_MASK) != 0;
-        bool collectFbOnGlDraw = (cmd & READ_FB_ON_GLDRAW_MASK) != 0;
-        bool collectTextureData = (cmd & READ_TEXTURE_DATA_ON_GLTEXIMAGE_MASK) != 0;
-
-        state->setCollectFbOnEglSwap(collectFbOnEglSwap);
-        state->setCollectFbOnGlDraw(collectFbOnGlDraw);
-        state->setCollectTextureDataOnGlTexImage(collectTextureData);
-
-        ALOGD("trace options: eglswap: %d, gldraw: %d, texImage: %d",
-            collectFbOnEglSwap, collectFbOnGlDraw, collectTextureData);
-    }
-
-    ALOGE("Stopping OpenGL Trace Command Receiver\n");
-
-    free(cmdBuf);
-    return NULL;
-}
-
-/**
- * Starts Trace Server and waits for connection from the host.
- * Returns -1 in case of connection error, 0 otherwise.
- */
-int GLTrace_start() {
-    int status = 0;
-    int clientSocket = -1;
-    TCPStream *stream = NULL;
-
-    pthread_mutex_lock(&sGlTraceStateLock);
-
-    if (sGlTraceInProgress) {
-        goto done;
-    }
-
-    char udsName[PROPERTY_VALUE_MAX];
-    property_get("debug.egl.debug_portname", udsName, "gltrace");
-    clientSocket = gltrace::acceptClientConnection(udsName);
-    if (clientSocket < 0) {
-        ALOGE("Error creating GLTrace server socket. Tracing disabled.");
-        status = -1;
-        goto done;
-    }
-
-    sGlTraceInProgress = 1;
-
-    // create communication channel to the host
-    stream = new TCPStream(clientSocket);
-
-    // initialize tracing state
-    sGLTraceState = new GLTraceState(stream);
-
-    pthread_create(&sReceiveThreadId, NULL, commandReceiveTask, sGLTraceState);
-
-done:
-    pthread_mutex_unlock(&sGlTraceStateLock);
-    return status;
-}
-
-void GLTrace_stop() {
-    pthread_mutex_lock(&sGlTraceStateLock);
-
-    if (sGlTraceInProgress) {
-        sGlTraceInProgress = 0;
-        delete sGLTraceState;
-        sGLTraceState = NULL;
-    }
-
-    pthread_mutex_unlock(&sGlTraceStateLock);
-}
-
-void GLTrace_eglCreateContext(int version, EGLContext c) {
-    pthread_mutex_lock(&sGlTraceStateLock);
-    GLTraceState *state = sGLTraceState;
-    pthread_mutex_unlock(&sGlTraceStateLock);
-
-    if (state == NULL) return;
-
-    // update trace state for new EGL context
-    GLTraceContext *traceContext = state->createTraceContext(version, c);
-    gltrace::setupTraceContextThreadSpecific(traceContext);
-
-    // trace command through to the host
-    gltrace::GLTrace_eglCreateContext(version, traceContext->getId());
-}
-
-void GLTrace_eglMakeCurrent(const unsigned version, gl_hooks_t *hooks, EGLContext c) {
-    pthread_mutex_lock(&sGlTraceStateLock);
-    GLTraceState *state = sGLTraceState;
-    pthread_mutex_unlock(&sGlTraceStateLock);
-
-    if (state == NULL) return;
-
-    // setup per context state
-    GLTraceContext *traceContext = state->getTraceContext(c);
-    if (traceContext == NULL) {
-        GLTrace_eglCreateContext(version, c);
-        traceContext = state->getTraceContext(c);
-    }
-
-    traceContext->hooks = hooks;
-    gltrace::setupTraceContextThreadSpecific(traceContext);
-
-    // trace command through to the host
-    gltrace::GLTrace_eglMakeCurrent(traceContext->getId());
-}
-
-void GLTrace_eglReleaseThread() {
-    gltrace::releaseContext();
-}
-
-void GLTrace_eglSwapBuffers(void *dpy, void *draw) {
-    gltrace::GLTrace_eglSwapBuffers(dpy, draw);
-}
-
-gl_hooks_t *GLTrace_getGLHooks() {
-    return gltrace::getGLHooks();
-}
-
-}
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
deleted file mode 100644
index a4a187a..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ /dev/null
@@ -1,920 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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 <cutils/log.h>
-#include <EGL/egldefs.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
-#include "gltrace_api.h"
-#include "gltrace_context.h"
-#include "gltrace_fixup.h"
-
-namespace android {
-namespace gltrace {
-
-GLint glGetInteger(GLTraceContext *context, GLenum param) {
-    GLint x;
-    context->hooks->gl.glGetIntegerv(param, &x);
-    return x;
-}
-
-GLint glGetVertexAttrib(GLTraceContext *context, GLuint index, GLenum pname) {
-    GLint x;
-    context->hooks->gl.glGetVertexAttribiv(index, pname, &x);
-    return x;
-}
-
-bool isUsingPixelBuffers(GLTraceContext *context) {
-    if (context->getVersionMajor() < 3) {
-        return false; // PBOs not supported prior to GLES 3.0
-    }
-    return glGetInteger(context, GL_PIXEL_UNPACK_BUFFER_BINDING) != 0;
-}
-
-bool isUsingArrayBuffers(GLTraceContext *context) {
-    return glGetInteger(context, GL_ARRAY_BUFFER_BINDING) != 0;
-}
-
-bool isUsingElementArrayBuffers(GLTraceContext *context) {
-    return glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING) != 0;
-}
-
-unsigned getBytesPerTexel(const GLenum format, const GLenum type) {
-    /*
-    Description from glTexImage2D spec:
-
-    Data is read from data as a sequence of unsigned bytes or shorts, depending on type.
-    When type is GL_UNSIGNED_BYTE, each of the bytes is interpreted as one color component.
-    When type is one of GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_4_4_4_4, or
-    GL_UNSIGNED_SHORT_5_5_5_1, each unsigned short value is interpreted as containing all
-    the components for a single texel, with the color components arranged according to
-    format. Color components are treated as groups of one, two, three, or four values,
-    again based on format. Groups of components are referred to as texels.
-
-    width × height texels are read from memory, starting at location data. By default,
-    these texels are taken from adjacent memory locations, except that after all width
-    texels are read, the read pointer is advanced to the next four-byte boundary.
-    The four-byte row alignment is specified by glPixelStorei with argument
-    GL_UNPACK_ALIGNMENT, and it can be set to one, two, four, or eight bytes.
-    */
-
-    switch (type) {
-    case GL_UNSIGNED_SHORT_5_6_5:
-    case GL_UNSIGNED_SHORT_4_4_4_4:
-    case GL_UNSIGNED_SHORT_5_5_5_1:
-        return 2;
-    case GL_UNSIGNED_BYTE:
-        break;
-    default:
-        ALOGE("GetBytesPerPixel: unknown type %x", type);
-    }
-
-    switch (format) {
-    case GL_ALPHA:
-    case GL_LUMINANCE:
-        return 1;
-    case GL_LUMINANCE_ALPHA:
-        return 2;
-    case GL_RGB:
-        return 3;
-    case GL_RGBA:
-    case 0x80E1: // GL_BGRA_EXT
-        return 4;
-    default:
-        ALOGE("GetBytesPerPixel: unknown format %x", format);
-    }
-
-    return 1;   // in doubt...
-}
-
-void fixup_GenericFloatArray(int argIndex, int nFloats, GLMessage *glmsg, void *src) {
-    GLMessage_DataType *arg_floatarray = glmsg->mutable_args(argIndex);
-    GLfloat *floatp = (GLfloat *)src;
-
-    if (floatp == NULL) {
-        return;
-    }
-
-    arg_floatarray->set_type(GLMessage::DataType::FLOAT);
-    arg_floatarray->set_isarray(true);
-    arg_floatarray->clear_floatvalue();
-
-    for (int i = 0; i < nFloats; i++, floatp++) {
-        arg_floatarray->add_floatvalue(*floatp);
-    }
-}
-
-void fixup_GenericIntArray(int argIndex, int nInts, GLMessage *glmsg, void *src) {
-    GLMessage_DataType *arg_intarray = glmsg->mutable_args(argIndex);
-    GLint *intp = (GLint *)src;
-
-    if (intp == NULL) {
-        return;
-    }
-
-    arg_intarray->set_type(GLMessage::DataType::INT);
-    arg_intarray->set_isarray(true);
-    arg_intarray->clear_intvalue();
-
-    for (int i = 0; i < nInts; i++, intp++) {
-        arg_intarray->add_intvalue(*intp);
-    }
-}
-
-void fixup_GenericEnumArray(int argIndex, int nEnums, GLMessage *glmsg, void *src) {
-    // fixup as if they were ints
-    fixup_GenericIntArray(argIndex, nEnums, glmsg, src);
-
-    // and then set the data type to be enum
-    GLMessage_DataType *arg_enumarray = glmsg->mutable_args(argIndex);
-    arg_enumarray->set_type(GLMessage::DataType::ENUM);
-}
-
-/** Generic helper function: extract pointer at argIndex and
-    replace it with the C style string at *pointer */
-void fixup_CStringPtr(int argIndex, GLMessage *glmsg, void *src) {
-    GLMessage_DataType *arg = glmsg->mutable_args(argIndex);
-    GLchar *ptr = (GLchar *) src;
-
-    arg->set_type(GLMessage::DataType::CHAR);
-    arg->set_isarray(true);
-    arg->add_charvalue(ptr);
-}
-
-void fixup_glGetString(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* const GLubyte* GLTrace_glGetString(GLenum name) */
-    GLMessage_DataType *ret = glmsg->mutable_returnvalue();
-    GLchar *ptr = (GLchar *) pointersToFixup[0];
-
-    if (ptr != NULL) {
-        ret->set_type(GLMessage::DataType::CHAR);
-        ret->set_isarray(true);
-        ret->add_charvalue(ptr);
-    }
-}
-
-/* Add the contents of the framebuffer to the protobuf message */
-void fixup_addFBContents(GLTraceContext *context, GLMessage *glmsg, FBBinding fbToRead) {
-    void *fbcontents;
-    unsigned fbsize, fbwidth, fbheight;
-    context->getCompressedFB(&fbcontents, &fbsize, &fbwidth, &fbheight, fbToRead);
-
-    GLMessage_FrameBuffer *fb = glmsg->mutable_fb();
-    fb->set_width(fbwidth);
-    fb->set_height(fbheight);
-    fb->add_contents(fbcontents, fbsize);
-}
-
-/** Common fixup routing for glTexImage2D & glTexSubImage2D. */
-void fixup_glTexImage(GLTraceContext *context, int widthIndex, int heightIndex, GLMessage *glmsg,
-                        void *dataSrc) {
-    GLMessage_DataType arg_width  = glmsg->args(widthIndex);
-    GLMessage_DataType arg_height = glmsg->args(heightIndex);
-
-    GLMessage_DataType arg_format = glmsg->args(6);
-    GLMessage_DataType arg_type   = glmsg->args(7);
-    GLMessage_DataType *arg_data  = glmsg->mutable_args(8);
-
-    GLsizei width  = arg_width.intvalue(0);
-    GLsizei height = arg_height.intvalue(0);
-    GLenum format  = arg_format.intvalue(0);
-    GLenum type    = arg_type.intvalue(0);
-    void *data     = (void *) dataSrc;
-
-    int bytesPerTexel = getBytesPerTexel(format, type);
-
-    arg_data->set_type(GLMessage::DataType::BYTE);
-    arg_data->clear_rawbytes();
-
-    if (data != NULL && !isUsingPixelBuffers(context)) {
-        arg_data->set_isarray(true);
-        arg_data->add_rawbytes(data, bytesPerTexel * width * height);
-    } else {
-        arg_data->set_isarray(false);
-        arg_data->set_type(GLMessage::DataType::VOID);
-    }
-}
-
-
-void fixup_glTexImage2D(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glTexImage2D(GLenum target,
-                        GLint level,
-                        GLint internalformat,
-                        GLsizei width,
-                        GLsizei height,
-                        GLint border,
-                        GLenum format,
-                        GLenum type,
-                        const GLvoid *data);
-    */
-    int widthIndex = 3;
-    int heightIndex = 4;
-    fixup_glTexImage(context, widthIndex, heightIndex, glmsg, pointersToFixup[0]);
-}
-
-void fixup_glTexSubImage2D(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
-    /*
-    void glTexSubImage2D(GLenum target,
-                        GLint level,
-                        GLint xoffset,
-                        GLint yoffset,
-                        GLsizei width,
-                        GLsizei height,
-                        GLenum format,
-                        GLenum type,
-                        const GLvoid * data);
-    */
-    int widthIndex = 4;
-    int heightIndex = 5;
-    fixup_glTexImage(context, widthIndex, heightIndex, glmsg, pointersToFixup[0]);
-}
-
-void fixup_glCompressedTexImage2D(GLTraceContext *context, GLMessage *glmsg,
-                                    void *pointersToFixup[]) {
-    /* void glCompressedTexImage2D(GLenum target,
-                                   GLint level,
-                                   GLenum internalformat,
-                                   GLsizei width,
-                                   GLsizei height,
-                                   GLint border,
-                                   GLsizei imageSize,
-                                   const GLvoid* data);
-    */
-    GLsizei size  = glmsg->args(6).intvalue(0);
-    void *data = pointersToFixup[0];
-
-    GLMessage_DataType *arg_data  = glmsg->mutable_args(7);
-    arg_data->set_type(GLMessage::DataType::BYTE);
-    arg_data->clear_rawbytes();
-
-    if (data != NULL && !isUsingPixelBuffers(context)) {
-        arg_data->set_isarray(true);
-        arg_data->add_rawbytes(data, size);
-    } else {
-        arg_data->set_isarray(false);
-        arg_data->set_type(GLMessage::DataType::VOID);
-    }
-}
-
-void fixup_glCompressedTexSubImage2D(GLTraceContext *context, GLMessage *glmsg,
-                                        void *pointersToFixup[]) {
-    /* void glCompressedTexSubImage2D(GLenum target,
-                                      GLint level,
-                                      GLint xoffset,
-                                      GLint yoffset,
-                                      GLsizei width,
-                                      GLsizei height,
-                                      GLenum format,
-                                      GLsizei imageSize,
-                                      const GLvoid* data);
-    */
-    GLsizei size  = glmsg->args(7).intvalue(0);
-    void *data = pointersToFixup[0];
-
-    GLMessage_DataType *arg_data  = glmsg->mutable_args(8);
-    arg_data->set_type(GLMessage::DataType::BYTE);
-    arg_data->clear_rawbytes();
-
-    if (data != NULL && !isUsingPixelBuffers(context)) {
-        arg_data->set_isarray(true);
-        arg_data->add_rawbytes(data, size);
-    } else {
-        arg_data->set_isarray(false);
-        arg_data->set_type(GLMessage::DataType::VOID);
-    }
-}
-
-void fixup_glShaderSource(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glShaderSource(GLuint shader, GLsizei count, const GLchar** string,
-                                    const GLint* length) */
-    GLMessage_DataType arg_count  = glmsg->args(1);
-    GLMessage_DataType arg_lenp   = glmsg->args(3);
-    GLMessage_DataType *arg_strpp = glmsg->mutable_args(2);
-
-    GLsizei count = arg_count.intvalue(0);
-    GLchar **stringpp = (GLchar **) pointersToFixup[0];
-    GLint *lengthp = (GLint *) pointersToFixup[1];
-
-    arg_strpp->set_type(GLMessage::DataType::CHAR);
-    arg_strpp->set_isarray(true);
-    arg_strpp->clear_charvalue();
-
-    ::std::string src = "";
-    for (int i = 0; i < count; i++) {
-        if (lengthp != NULL)
-            src.append(*stringpp++, *lengthp++);
-        else
-            src.append(*stringpp++);  // assume null terminated
-    }
-
-    arg_strpp->add_charvalue(src);
-}
-
-void fixup_glUniformGenericInteger(int argIndex, int nElemsPerVector, GLMessage *glmsg,
-                                                                    void *pointersToFixup[]) {
-    /* void glUniform?iv(GLint location, GLsizei count, const GLint *value); */
-    GLMessage_DataType arg_count  = glmsg->args(1);
-    int n_vectors = arg_count.intvalue(0);
-    fixup_GenericIntArray(argIndex, nElemsPerVector * n_vectors, glmsg, pointersToFixup[0]);
-}
-
-void fixup_glUniformGeneric(int argIndex, int nElemsPerVector, GLMessage *glmsg, void *src) {
-    GLMessage_DataType arg_count  = glmsg->args(1);
-    int n_vectors = arg_count.intvalue(0);
-    fixup_GenericFloatArray(argIndex, nElemsPerVector * n_vectors, glmsg, src);
-}
-
-void fixup_glUniformMatrixGeneric(int matrixSize, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glUniformMatrix?fv(GLint location, GLsizei count, GLboolean transpose,
-                                                                const GLfloat* value) */
-    GLMessage_DataType arg_count  = glmsg->args(1);
-    int n_matrices = arg_count.intvalue(0);
-    fixup_glUniformGeneric(3, matrixSize * matrixSize * n_matrices, glmsg, pointersToFixup[0]);
-}
-
-void fixup_glGenGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glGen*(GLsizei n, GLuint * buffers); */
-    GLMessage_DataType arg_n  = glmsg->args(0);
-    GLsizei n = arg_n.intvalue(0);
-
-    fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
-}
-
-void fixup_glDeleteGeneric(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glDelete*(GLsizei n, GLuint *buffers); */
-    GLMessage_DataType arg_n  = glmsg->args(0);
-    GLsizei n = arg_n.intvalue(0);
-
-    fixup_GenericIntArray(1, n, glmsg, pointersToFixup[0]);
-}
-
-void fixup_glGetBooleanv(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glGetBooleanv(GLenum pname, GLboolean *params); */
-    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
-    GLboolean *src = (GLboolean*) pointersToFixup[0];
-
-    arg_params->set_type(GLMessage::DataType::BOOL);
-    arg_params->set_isarray(true);
-    arg_params->clear_boolvalue();
-    arg_params->add_boolvalue(*src);
-}
-
-void fixup_glGetFloatv(GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glGetFloatv(GLenum pname, GLfloat *params); */
-    GLMessage_DataType *arg_params = glmsg->mutable_args(1);
-    GLfloat *src = (GLfloat*) pointersToFixup[0];
-
-    arg_params->set_type(GLMessage::DataType::FLOAT);
-    arg_params->set_isarray(true);
-    arg_params->clear_floatvalue();
-    arg_params->add_floatvalue(*src);
-}
-
-void fixup_glLinkProgram(GLMessage *glmsg) {
-    /* void glLinkProgram(GLuint program); */
-    GLuint program = glmsg->args(0).intvalue(0);
-
-    /* We don't have to fixup this call, but as soon as a program is linked,
-       we obtain information about all active attributes and uniforms to
-       pass on to the debugger. Note that in order to pass this info to
-       the debugger, all we need to do is call the trace versions of the
-       necessary calls. */
-
-    GLint n, maxNameLength;
-    GLchar *name;
-    GLint size;
-    GLenum type;
-
-    // obtain info regarding active attributes
-    GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &n);
-    GLTrace_glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxNameLength);
-
-    name = (GLchar *) malloc(maxNameLength);
-    for (int i = 0; i < n; i++) {
-        GLTrace_glGetActiveAttrib(program, i, maxNameLength, NULL, &size, &type, name);
-    }
-    free(name);
-
-    // obtain info regarding active uniforms
-    GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n);
-    GLTrace_glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
-
-    name = (GLchar *) malloc(maxNameLength);
-    for (int i = 0; i < n; i++) {
-        GLTrace_glGetActiveUniform(program, i, maxNameLength, NULL, &size, &type, name);
-    }
-    free(name);
-}
-
-/** Given a glGetActive[Uniform|Attrib] call, obtain the location
- *  of the variable of given name in the call.
- */
-GLint getShaderVariableLocation(GLTraceContext *context, GLMessage *glmsg, GLchar *name) {
-    GLMessage_Function func = glmsg->function();
-    if (func != GLMessage::glGetActiveAttrib && func != GLMessage::glGetActiveUniform) {
-        return -1;
-    }
-
-    int program = glmsg->args(0).intvalue(0);
-
-    if (func == GLMessage::glGetActiveAttrib) {
-        return context->hooks->gl.glGetAttribLocation(program, name);
-    } else {
-        return context->hooks->gl.glGetUniformLocation(program, name);
-    }
-}
-
-void fixup_glGetActiveAttribOrUniform(GLTraceContext *context, GLMessage *glmsg,
-                                                                void *pointersToFixup[]) {
-    /* void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize,
-                GLsizei* length, GLint* size, GLenum* type, GLchar* name); */
-    /* void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize,
-                GLsizei* length, GLint* size, GLenum* type, GLchar* name) */
-
-    fixup_GenericIntArray(3, 1, glmsg, pointersToFixup[0]);     // length
-    fixup_GenericIntArray(4, 1, glmsg, pointersToFixup[1]);     // size
-    fixup_GenericEnumArray(5, 1, glmsg, pointersToFixup[2]);    // type
-    fixup_CStringPtr(6, glmsg, pointersToFixup[3]);             // name
-
-    // The index argument in the glGetActive[Attrib|Uniform] functions
-    // does not correspond to the actual location index as used in
-    // glUniform*() or glVertexAttrib*() to actually upload the data.
-    // In order to make things simpler for the debugger, we also pass
-    // a hidden location argument that stores the actual location.
-    // append the location value to the end of the argument list
-    GLint location = getShaderVariableLocation(context, glmsg, (GLchar*)pointersToFixup[3]);
-    GLMessage_DataType *arg_location = glmsg->add_args();
-    arg_location->set_isarray(false);
-    arg_location->set_type(GLMessage::DataType::INT);
-    arg_location->add_intvalue(location);
-}
-
-/** Copy @len bytes of data from @src into the @dataIndex'th argument of the message. */
-void addGlBufferData(GLMessage *glmsg, int dataIndex, GLvoid *src, GLsizeiptr len) {
-    GLMessage_DataType *arg_datap = glmsg->mutable_args(dataIndex);
-    arg_datap->set_type(GLMessage::DataType::VOID);
-    arg_datap->set_isarray(true);
-    arg_datap->clear_intvalue();
-    arg_datap->add_rawbytes(src, len);
-}
-
-void fixup_glBufferData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
-    GLsizeiptr size = glmsg->args(1).intvalue(0);
-    GLvoid *datap = (GLvoid *) pointersToFixup[0];
-
-    // Save element array buffers for future use to fixup glVertexAttribPointers
-    // when a glDrawElements() call is performed.
-    GLenum target = glmsg->args(0).intvalue(0);
-    if (target == GL_ELEMENT_ARRAY_BUFFER) {
-        GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
-        context->bindBuffer(bufferId, datap, size);
-    }
-
-    // add buffer data to the protobuf message
-    if (datap != NULL) {
-        addGlBufferData(glmsg, 2, datap, size);
-    }
-}
-
-void fixup_glBufferSubData(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
-    GLenum target = glmsg->args(0).intvalue(0);
-    GLintptr offset = glmsg->args(1).intvalue(0);
-    GLsizeiptr size = glmsg->args(2).intvalue(0);
-    GLvoid *datap = (GLvoid *) pointersToFixup[0];
-    if (target == GL_ELEMENT_ARRAY_BUFFER) {
-        GLint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
-        context->updateBufferSubData(bufferId, offset, datap, size);
-    }
-
-    // add buffer data to the protobuf message
-    addGlBufferData(glmsg, 3, datap, size);
-}
-
-/** Obtain the size of each vertex attribute. */
-int vertexAttribSize(GLenum type, GLsizei numComponents) {
-    int sizePerComponent;
-
-    switch(type) {
-    case GL_BYTE:
-    case GL_UNSIGNED_BYTE:
-        sizePerComponent = 1;
-        break;
-    case GL_SHORT:
-    case GL_UNSIGNED_SHORT:
-        sizePerComponent = 2;
-        break;
-    case GL_FIXED:
-    case GL_FLOAT:
-    default:
-        sizePerComponent = 4;
-        break;
-    }
-
-    return sizePerComponent * numComponents;
-}
-
-/** Create and send a glVertexAttribPointerData trace message to the host. */
-void trace_glVertexAttribPointerData(GLTraceContext *context,
-                    GLuint indx, GLint size, GLenum type,
-                    GLboolean normalized, GLsizei stride, const GLvoid* ptr,
-                    GLuint minIndex, GLuint maxIndex, nsecs_t startTime) {
-    /* void glVertexAttribPointerData(GLuint indx, GLint size, GLenum type,
-                    GLboolean normalized, GLsizei stride, const GLvoid* ptr,
-                    int minIndex, int maxIndex) */
-    GLMessage glmsg;
-    GLTraceContext *glContext = context;
-
-    glmsg.set_function(GLMessage::glVertexAttribPointerData);
-
-    // copy argument indx
-    GLMessage_DataType *arg_indx = glmsg.add_args();
-    arg_indx->set_isarray(false);
-    arg_indx->set_type(GLMessage::DataType::INT);
-    arg_indx->add_intvalue(indx);
-
-    // copy argument size
-    GLMessage_DataType *arg_size = glmsg.add_args();
-    arg_size->set_isarray(false);
-    arg_size->set_type(GLMessage::DataType::INT);
-    arg_size->add_intvalue(size);
-
-    // copy argument type
-    GLMessage_DataType *arg_type = glmsg.add_args();
-    arg_type->set_isarray(false);
-    arg_type->set_type(GLMessage::DataType::ENUM);
-    arg_type->add_intvalue((int)type);
-
-    // copy argument normalized
-    GLMessage_DataType *arg_normalized = glmsg.add_args();
-    arg_normalized->set_isarray(false);
-    arg_normalized->set_type(GLMessage::DataType::BOOL);
-    arg_normalized->add_boolvalue(normalized);
-
-    // copy argument stride
-    GLMessage_DataType *arg_stride = glmsg.add_args();
-    arg_stride->set_isarray(false);
-    arg_stride->set_type(GLMessage::DataType::INT);
-    arg_stride->add_intvalue(stride);
-
-    // copy argument ptr
-    GLMessage_DataType *arg_ptr = glmsg.add_args();
-    arg_ptr->set_isarray(true);
-    arg_ptr->set_type(GLMessage::DataType::BYTE);
-    int perVertexSize = vertexAttribSize(type, size);
-    GLchar *p = (GLchar*) ptr;
-    std::string data;
-    for (GLuint i = minIndex; i < maxIndex; i++) {
-        data.append(p, perVertexSize);
-        p += stride == 0 ? perVertexSize : stride;
-    }
-    arg_ptr->add_rawbytes(data);
-
-    // copy argument min index
-    GLMessage_DataType *arg_min = glmsg.add_args();
-    arg_min->set_isarray(false);
-    arg_min->set_type(GLMessage::DataType::INT);
-    arg_min->add_intvalue(minIndex);
-
-    // copy argument max index
-    GLMessage_DataType *arg_max = glmsg.add_args();
-    arg_max->set_isarray(false);
-    arg_max->set_type(GLMessage::DataType::INT);
-    arg_max->add_intvalue(maxIndex);
-
-    glmsg.set_context_id(context->getId());
-    glmsg.set_start_time(startTime);
-    glmsg.set_threadtime(0);
-    glmsg.set_duration(0);
-
-    context->traceGLMessage(&glmsg);
-}
-
-void findMinAndMaxIndices(GLvoid *indices, GLsizei count, GLenum type,
-                            GLuint *minIndex, GLuint *maxIndex) {
-    GLuint index;
-    *minIndex = UINT_MAX;
-    *maxIndex = 0;
-
-    if (indices == NULL) {
-        return;
-    }
-
-    for (GLsizei i = 0; i < count; i++) {
-        if (type == GL_UNSIGNED_BYTE) {
-            index = *((GLubyte*) indices + i);
-        } else {
-            index = *((GLushort*) indices + i);
-        }
-
-        if (index < *minIndex) *minIndex = index;
-        if (index > *maxIndex) *maxIndex = index;
-    }
-}
-
-void trace_VertexAttribPointerData(GLTraceContext *context,
-                            GLuint minIndex, GLuint maxIndex, nsecs_t time) {
-    GLuint maxAttribs = glGetInteger(context, GL_MAX_VERTEX_ATTRIBS);
-    for (GLuint index = 0; index < maxAttribs; index++) {
-        if (!glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_ENABLED)) {
-            // vertex array disabled
-            continue;
-        }
-
-        if (glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING)) {
-            // vbo
-            continue;
-        }
-
-        GLint size = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_SIZE);
-        GLenum type = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_TYPE);
-        GLboolean norm = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED);
-        GLsizei stride = glGetVertexAttrib(context, index, GL_VERTEX_ATTRIB_ARRAY_STRIDE);
-        GLvoid* ptr;
-        context->hooks->gl.glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr);
-
-        trace_glVertexAttribPointerData(context,
-                    index, size, type, norm, stride, ptr,
-                    minIndex, maxIndex, time);
-    }
-}
-
-void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
-    if (context->getVersion() == egl_connection_t::GLESv1_INDEX) {
-        // only supported for GLES2 and above
-        return;
-    }
-
-    /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
-    GLsizei count = glmsg->args(2).intvalue(0);
-
-    // Vertex attrib pointer data patchup calls should appear as if
-    // they occurred right before the draw call.
-    nsecs_t time = glmsg->start_time() - 1;
-
-    trace_VertexAttribPointerData(context, 0, count, time);
-}
-
-void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg,
-                            GLvoid *indices) {
-    if (context->getVersion() == egl_connection_t::GLESv1_INDEX) {
-        // only supported for GLES2 and above
-        return;
-    }
-
-    /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
-    GLsizei count = glmsg->args(1).intvalue(0);
-    GLenum type = glmsg->args(2).intvalue(0);
-    GLuint index;
-
-    GLuint minIndex, maxIndex;
-
-    // The index buffer is either passed in as an argument to the glDrawElements() call,
-    // or it is stored in the current GL_ELEMENT_ARRAY_BUFFER.
-    GLvoid *indexBuffer;
-    if (isUsingElementArrayBuffers(context)) {
-        GLsizeiptr eaBufferSize;
-        GLuint bufferId = glGetInteger(context, GL_ELEMENT_ARRAY_BUFFER_BINDING);
-        context->getBuffer(bufferId, &indexBuffer, &eaBufferSize);
-    } else {
-        indexBuffer = indices;
-    }
-
-    // Rather than sending vertex attribute data that corresponds to the indices
-    // being drawn, we send the vertex attribute data for the entire range of
-    // indices being drawn, including the ones not drawn. The min & max indices
-    // provide the range of indices being drawn.
-    findMinAndMaxIndices(indexBuffer, count, type, &minIndex, &maxIndex);
-
-    // Vertex attrib pointer data patchup calls should appear as if
-    // they occurred right before the draw call.
-    nsecs_t time = glmsg->start_time() - 1;
-
-    trace_VertexAttribPointerData(context, minIndex, maxIndex + 1, time);
-}
-
-void fixup_glDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
-    // Trace all vertex attribute data stored in client space.
-    trace_VertexAttribPointerDataForGlDrawArrays(context, glmsg);
-
-    // Attach the FB if requested
-    if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
-        fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
-    }
-}
-
-void fixup_glDrawElements(GLTraceContext *context, GLMessage *glmsg, void *pointersToFixup[]) {
-    /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
-    GLvoid *indices = pointersToFixup[0];
-    GLenum type = glmsg->args(2).intvalue(0);
-    GLsizei count = glmsg->args(1).intvalue(0);
-    GLuint index;
-
-    // Trace all vertex attribute data stored in client space.
-    trace_VertexAttribPointerDataForGlDrawElements(context, glmsg, indices);
-
-    // Fixup indices argument
-    if (!isUsingElementArrayBuffers(context)) {
-        GLMessage_DataType *arg_indices = glmsg->mutable_args(3);
-        arg_indices->set_isarray(true);
-        arg_indices->clear_intvalue();
-        arg_indices->set_type(GLMessage::DataType::INT);
-        for (GLsizei i = 0; i < count; i++) {
-            if (type == GL_UNSIGNED_BYTE) {
-                index = *((GLubyte*) indices + i);
-            } else {
-                index = *((GLushort*) indices + i);
-            }
-            arg_indices->add_intvalue(index);
-        }
-    }
-
-    // Attach the FB if requested
-    if (context->getGlobalTraceState()->shouldCollectFbOnGlDraw()) {
-        fixup_addFBContents(context, glmsg, CURRENTLY_BOUND_FB);
-    }
-}
-
-void fixupGLMessage(GLTraceContext *context, nsecs_t wallStart, nsecs_t wallEnd,
-                                             nsecs_t threadStart, nsecs_t threadEnd,
-                                             GLMessage *glmsg, void *pointersToFixup[]) {
-    // for all messages, set the current context id
-    glmsg->set_context_id(context->getId());
-
-    // set start time and duration
-    glmsg->set_start_time(wallStart);
-    glmsg->set_duration((unsigned)(wallEnd - wallStart));
-    glmsg->set_threadtime((unsigned)(threadEnd - threadStart));
-
-    // do any custom message dependent processing
-    switch (glmsg->function()) {
-    case GLMessage::glDeleteBuffers:      /* glDeleteBuffers(GLsizei n, GLuint *buffers); */
-    case GLMessage::glDeleteFramebuffers: /* glDeleteFramebuffers(GLsizei n, GLuint *buffers); */
-    case GLMessage::glDeleteRenderbuffers:/* glDeleteRenderbuffers(GLsizei n, GLuint *buffers); */
-    case GLMessage::glDeleteTextures:     /* glDeleteTextures(GLsizei n, GLuint *textures); */
-        fixup_glDeleteGeneric(glmsg, pointersToFixup);
-        break;
-    case GLMessage::glGenBuffers:        /* void glGenBuffers(GLsizei n, GLuint *buffers); */
-    case GLMessage::glGenFramebuffers:   /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
-    case GLMessage::glGenRenderbuffers:  /* void glGenFramebuffers(GLsizei n, GLuint *buffers); */
-    case GLMessage::glGenTextures:       /* void glGenTextures(GLsizei n, GLuint *textures); */
-        fixup_glGenGeneric(glmsg, pointersToFixup);
-        break;
-    case GLMessage::glLinkProgram:       /* void glLinkProgram(GLuint program); */
-        fixup_glLinkProgram(glmsg);
-        break;
-    case GLMessage::glGetActiveAttrib:
-        fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glGetActiveUniform:
-        fixup_glGetActiveAttribOrUniform(context, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glBindAttribLocation:
-        /* void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name); */
-        fixup_CStringPtr(2, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glGetAttribLocation:
-    case GLMessage::glGetUniformLocation:
-        /* int glGetAttribLocation(GLuint program, const GLchar* name) */
-        /* int glGetUniformLocation(GLuint program, const GLchar* name) */
-        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glGetBooleanv:
-        fixup_glGetBooleanv(glmsg, pointersToFixup);
-        break;
-    case GLMessage::glGetFloatv:
-        fixup_glGetFloatv(glmsg, pointersToFixup);
-        break;
-    case GLMessage::glGetIntegerv:        /* void glGetIntegerv(GLenum pname, GLint *params); */
-        fixup_GenericIntArray(1, 1, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glGetProgramiv:
-    case GLMessage::glGetRenderbufferParameteriv:
-    case GLMessage::glGetShaderiv:
-        /* void glGetProgramiv(GLuint program, GLenum pname, GLint* params) */
-        /* void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) */
-        /* void glGetShaderiv(GLuint shader, GLenum pname, GLint* params) */
-        fixup_GenericIntArray(2, 1, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glGetString:
-        fixup_glGetString(glmsg, pointersToFixup);
-        break;
-    case GLMessage::glTexImage2D:
-        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glTexImage2D(context, glmsg, pointersToFixup);
-        }
-        break;
-    case GLMessage::glTexSubImage2D:
-        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glTexSubImage2D(context, glmsg, pointersToFixup);
-        }
-        break;
-    case GLMessage::glCompressedTexImage2D:
-        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glCompressedTexImage2D(context, glmsg, pointersToFixup);
-        }
-        break;
-    case GLMessage::glCompressedTexSubImage2D:
-        if (context->getGlobalTraceState()->shouldCollectTextureDataOnGlTexImage()) {
-            fixup_glCompressedTexSubImage2D(context, glmsg, pointersToFixup);
-        }
-        break;
-    case GLMessage::glShaderSource:
-        fixup_glShaderSource(glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniform1iv:
-        /* void glUniform1iv(GLint location, GLsizei count, const GLint *value); */
-        fixup_glUniformGenericInteger(2, 1, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniform2iv:
-        /* void glUniform2iv(GLint location, GLsizei count, const GLint *value); */
-        fixup_glUniformGenericInteger(2, 2, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniform3iv:
-        /* void glUniform3iv(GLint location, GLsizei count, const GLint *value); */
-        fixup_glUniformGenericInteger(2, 3, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniform4iv:
-        /* void glUniform4iv(GLint location, GLsizei count, const GLint *value); */
-        fixup_glUniformGenericInteger(2, 4, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniform1fv:
-        /* void glUniform1fv(GLint location, GLsizei count, const GLfloat *value); */
-        fixup_glUniformGeneric(2, 1, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glUniform2fv:
-        /* void glUniform2fv(GLint location, GLsizei count, const GLfloat *value); */
-        fixup_glUniformGeneric(2, 2, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glUniform3fv:
-        /* void glUniform3fv(GLint location, GLsizei count, const GLfloat *value); */
-        fixup_glUniformGeneric(2, 3, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glUniform4fv:
-        /* void glUniform4fv(GLint location, GLsizei count, const GLfloat *value); */
-        fixup_glUniformGeneric(2, 4, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glUniformMatrix2fv:
-        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
-                                                                    const GLfloat* value) */
-        fixup_glUniformMatrixGeneric(2, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniformMatrix3fv:
-        /* void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
-                                                                    const GLfloat* value) */
-        fixup_glUniformMatrixGeneric(3, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glUniformMatrix4fv:
-        /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
-                                                                    const GLfloat* value) */
-        fixup_glUniformMatrixGeneric(4, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glBufferData:
-        /* void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) */
-        fixup_glBufferData(context, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glBufferSubData:
-        /* void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) */
-        fixup_glBufferSubData(context, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glDrawArrays:
-        /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
-        fixup_glDrawArrays(context, glmsg);
-        break;
-    case GLMessage::glDrawElements:
-        /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
-        fixup_glDrawElements(context, glmsg, pointersToFixup);
-        break;
-    case GLMessage::glPushGroupMarkerEXT:
-        /* void PushGroupMarkerEXT(sizei length, const char *marker); */
-        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
-        break;
-    case GLMessage::glInsertEventMarkerEXT:
-        /* void InsertEventMarkerEXT(sizei length, const char *marker); */
-        fixup_CStringPtr(1, glmsg, pointersToFixup[0]);
-        break;
-    default:
-        break;
-    }
-}
-
-};
-};
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.h b/opengl/libs/GLES_trace/src/gltrace_fixup.h
deleted file mode 100644
index c90dbeb..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef __GLTRACE_FIXUP_H_
-#define __GLTRACE_FIXUP_H_
-
-#include <utils/Timers.h>
-
-#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
-#include "gltrace_context.h"
-
-namespace android {
-namespace gltrace {
-
-void fixupGLMessage(GLTraceContext *curContext, nsecs_t wallStart, nsecs_t wallEnd,
-                                                nsecs_t threadStart, nsecs_t threadEnd,
-                                                GLMessage *message, void *pointersToFixup[]);
-void fixup_addFBContents(GLTraceContext *curContext, GLMessage *message, FBBinding fbToRead);
-
-};
-};
-
-#endif
diff --git a/opengl/libs/GLES_trace/src/gltrace_hooks.cpp b/opengl/libs/GLES_trace/src/gltrace_hooks.cpp
deleted file mode 100644
index de8d463..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_hooks.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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 "hooks.h"
-#include "gltrace_api.h"
-#include "gltrace_hooks.h"
-
-namespace android {
-namespace gltrace {
-
-// Hook up all the GLTrace functions
-#define GL_ENTRY(_r, _api, ...) GLTrace_ ## _api,
-EGLAPI gl_hooks_t gHooksDebug = {
-    {
-        #include "entries.in"
-    },
-    {
-        {0}
-    }
-};
-#undef GL_ENTRY
-
-gl_hooks_t *getGLHooks() {
-    return &gHooksDebug;
-}
-
-};
-};
diff --git a/opengl/libs/GLES_trace/src/gltrace_transport.cpp b/opengl/libs/GLES_trace/src/gltrace_transport.cpp
deleted file mode 100644
index 2996d32..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_transport.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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 <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <unistd.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <netinet/in.h>
-
-#include <cutils/log.h>
-#include <private/android_filesystem_config.h>
-
-#include "gltrace_transport.h"
-
-namespace android {
-namespace gltrace {
-
-int acceptClientConnection(char *sockname) {
-    int serverSocket = socket(AF_LOCAL, SOCK_STREAM, 0);
-    if (serverSocket < 0) {
-        ALOGE("Error (%d) while creating socket. Check if app has network permissions.",
-                                                                            serverSocket);
-        return -1;
-    }
-
-    struct sockaddr_un server, client;
-
-    memset(&server, 0, sizeof server);
-    server.sun_family = AF_UNIX;
-    // the first byte of sun_path should be '\0' for abstract namespace
-    strcpy(server.sun_path + 1, sockname);
-
-    // note that sockaddr_len should be set to the exact size of the buffer that is used.
-    socklen_t sockaddr_len = sizeof(server.sun_family) + strlen(sockname) + 1;
-    if (bind(serverSocket, (struct sockaddr *) &server, sockaddr_len) < 0) {
-        close(serverSocket);
-        ALOGE("Failed to bind the server socket");
-        return -1;
-    }
-
-    if (listen(serverSocket, 1) < 0) {
-        close(serverSocket);
-        ALOGE("Failed to listen on server socket");
-        return -1;
-    }
-
-    ALOGD("gltrace::waitForClientConnection: server listening @ path %s", sockname);
-
-    int clientSocket = accept(serverSocket, (struct sockaddr *)&client, &sockaddr_len);
-    if (clientSocket < 0) {
-        close(serverSocket);
-        ALOGE("Failed to accept client connection");
-        return -1;
-    }
-
-    struct ucred cr;
-    socklen_t cr_len = sizeof(cr);
-    if (getsockopt(clientSocket, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) != 0) {
-        ALOGE("Error obtaining credentials of peer");
-        return -1;
-    }
-
-    // Only accept connects from the shell (adb forward comes to us as shell user),
-    // or the root user.
-    if (cr.uid != AID_SHELL && cr.uid != AID_ROOT) {
-        ALOGE("Unknown peer type (%d), expected shell to be the peer", cr.uid);
-        return -1;
-    }
-
-    ALOGD("gltrace::waitForClientConnection: client connected.");
-
-    // do not accept any more incoming connections
-    close(serverSocket);
-
-    return clientSocket;
-}
-
-TCPStream::TCPStream(int socket) {
-    mSocket = socket;
-    pthread_mutex_init(&mSocketWriteMutex, NULL);
-}
-
-TCPStream::~TCPStream() {
-    pthread_mutex_destroy(&mSocketWriteMutex);
-}
-
-void TCPStream::closeStream() {
-    if (mSocket > 0) {
-        close(mSocket);
-        mSocket = 0;
-    }
-}
-
-int TCPStream::send(void *buf, size_t len) {
-    if (mSocket <= 0) {
-        return -1;
-    }
-
-    pthread_mutex_lock(&mSocketWriteMutex);
-    int n = write(mSocket, buf, len);
-    pthread_mutex_unlock(&mSocketWriteMutex);
-
-    return n;
-}
-
-int TCPStream::receive(void *data, size_t len) {
-    if (mSocket <= 0) {
-        return -1;
-    }
-
-    size_t totalRead = 0;
-    while (totalRead < len) {
-        int n = read(mSocket, (uint8_t*)data + totalRead, len - totalRead);
-        if (n < 0) {
-            ALOGE("Error receiving data from stream: %d", errno);
-            return -1;
-        }
-
-        totalRead += n;
-    }
-
-    return 0;
-}
-
-BufferedOutputStream::BufferedOutputStream(TCPStream *stream, size_t bufferSize) {
-    mStream = stream;
-
-    mBufferSize = bufferSize;
-    mStringBuffer = "";
-    mStringBuffer.reserve(bufferSize);
-}
-
-int BufferedOutputStream::flush() {
-    if (mStringBuffer.size() == 0) {
-        return 0;
-    }
-
-    int n = mStream->send((void *)mStringBuffer.data(), mStringBuffer.size());
-    mStringBuffer.clear();
-    return n;
-}
-
-void BufferedOutputStream::enqueueMessage(GLMessage *msg) {
-    const uint32_t len = msg->ByteSize();
-
-    mStringBuffer.append((const char *)&len, sizeof(len));    // append header
-    msg->AppendToString(&mStringBuffer);                      // append message
-}
-
-int BufferedOutputStream::send(GLMessage *msg) {
-    enqueueMessage(msg);
-
-    if (mStringBuffer.size() > mBufferSize) {
-        return flush();
-    }
-
-    return 0;
-}
-
-};  // namespace gltrace
-};  // namespace android
diff --git a/opengl/libs/GLES_trace/src/gltrace_transport.h b/opengl/libs/GLES_trace/src/gltrace_transport.h
deleted file mode 100644
index fd6cb8c..0000000
--- a/opengl/libs/GLES_trace/src/gltrace_transport.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef __GLTRACE_TRANSPORT_H_
-#define __GLTRACE_TRANSPORT_H_
-
-#include <pthread.h>
-
-#include "frameworks/native/opengl/libs/GLES_trace/proto/gltrace.pb.h"
-
-namespace android {
-namespace gltrace {
-
-/**
- * TCPStream provides a TCP based communication channel from the device to
- * the host for transferring GLMessages.
- */
-class TCPStream {
-    int mSocket;
-    pthread_mutex_t mSocketWriteMutex;
-public:
-    /** Create a TCP based communication channel over @socket */
-    TCPStream(int socket);
-    ~TCPStream();
-
-    /** Close the channel. */
-    void closeStream();
-
-    /** Send @data of size @len to host. . Returns -1 on error, 0 on success. */
-    int send(void *data, size_t len);
-
-    /**
-     * Receive @len bytes of data into @buf from the remote end. This is a blocking call.
-     * Returns -1 on failure, 0 on success.
-     */
-    int receive(void *buf, size_t len);
-};
-
-/**
- * BufferedOutputStream provides buffering of data sent to the underlying
- * unbuffered channel.
- */
-class BufferedOutputStream {
-    TCPStream *mStream;
-
-    size_t mBufferSize;
-    std::string mStringBuffer;
-
-    /** Enqueue message into internal buffer. */
-    void enqueueMessage(GLMessage *msg);
-public:
-    /**
-     * Construct a Buffered stream of size @bufferSize, using @stream as
-     * its underlying channel for transport.
-     */
-    BufferedOutputStream(TCPStream *stream, size_t bufferSize);
-
-    /**
-     * Send @msg. The message could be buffered and sent later with a
-     * subsequent message. Returns -1 on error, 0 on success.
-     */
-    int send(GLMessage *msg);
-
-    /** Send any buffered messages, returns -1 on error, 0 on success. */
-    int flush();
-};
-
-/**
- * Utility method: start a server listening at @sockName (unix domain socket,
- * abstract namespace path), and wait for a client connection.
- * Returns the connected client socket on success, or -1 on failure.
- */
-int acceptClientConnection(char *sockName);
-
-};
-};
-
-#endif
diff --git a/opengl/libs/GLES_trace/tools/genapi.py b/opengl/libs/GLES_trace/tools/genapi.py
deleted file mode 100755
index c44b985..0000000
--- a/opengl/libs/GLES_trace/tools/genapi.py
+++ /dev/null
@@ -1,416 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2011 Google 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.
-#
-# ABOUT
-#   This script is used to generate the trace implementations of all
-#   OpenGL calls. When executed, it reads the specs for the OpenGL calls
-#   from the files GLES2/gl2_api.in, GLES2/gl2ext_api.in, GLES_CM/gl_api.in,
-#   and GLES_CM/glext_api.in, and generates trace versions for all the
-#   defined functions.
-#
-# PREREQUISITES
-#   To generate C++ files, this script uses the 'pyratemp' template
-#   module. The only reason to use pyratemp is that it is extremly
-#   simple to install:
-#   $ wget http://www.simple-is-better.org/template/pyratemp-0.3.2.tgz
-#   Extract and put the pyratemp.py file in the GLES_trace/tools folder,
-#   or update PYTHONPATH to point to wherever it was downloaded.
-#
-# USAGE
-#   $ cd GLES_trace       - run the program from GLES2_trace folder
-#   $ ./tools/genapi.py   - generates a .cpp and .h file
-#   $ mv *.cpp *.h src/   - move the generated files into the src folder
-
-import sys
-import re
-import pyratemp
-
-# Constants corresponding to the protobuf DataType.Type
-class DataType:
-    def __init__(self, name):
-        self.name = name
-
-    def __str__(self):
-        if self.name == "pointer":  # pointers map to the INT64 DataType
-            return "INT64"
-        return self.name.upper()
-
-    def getProtobufCall(self):
-        if self.name == "void":
-            raise ValueError("Attempt to set void value")
-        elif self.name == "char" or self.name == "byte" \
-                or self.name == "enum":
-            return "add_intvalue((int)"
-        elif self.name == "pointer":
-            return "add_int64value((uintptr_t)"
-        elif self.name == "int":
-            return "add_intvalue("
-        elif self.name == "float":
-            return "add_floatvalue("
-        elif self.name == "bool":
-            return "add_boolvalue("
-        elif self.name == "int64":
-            return "add_int64value("
-        else:
-            raise ValueError("Unknown value type %s" % self.name)
-
-DataType.VOID = DataType("void")
-DataType.CHAR = DataType("char")
-DataType.BYTE = DataType("byte")
-DataType.ENUM = DataType("enum")
-DataType.BOOL = DataType("bool")
-DataType.INT = DataType("int")
-DataType.FLOAT = DataType("float")
-DataType.POINTER = DataType("pointer")
-DataType.INT64 = DataType("int64")
-
-# mapping of GL types to protobuf DataType
-GLPROTOBUF_TYPE_MAP = {
-    "GLvoid":DataType.VOID,
-    "void":DataType.VOID,
-    "GLchar":DataType.CHAR,
-    "GLenum":DataType.ENUM,
-    "GLboolean":DataType.BOOL,
-    "GLbitfield":DataType.INT,
-    "GLbyte":DataType.BYTE,
-    "GLshort":DataType.INT,
-    "GLint":DataType.INT,
-    "int":DataType.INT,
-    "GLsizei":DataType.INT,
-    "GLubyte":DataType.BYTE,
-    "GLushort":DataType.INT,
-    "GLuint":DataType.INT,
-    "GLfloat":DataType.FLOAT,
-    "GLclampf":DataType.FLOAT,
-    "GLfixed":DataType.INT,
-    "GLclampx":DataType.INT,
-    "GLsizeiptr":DataType.INT,
-    "GLintptr":DataType.INT,
-    "GLeglImageOES":DataType.POINTER,
-    "GLint64":DataType.INT64,
-    "GLuint64":DataType.INT64,
-    "GLsync":DataType.POINTER,
-    "GLDEBUGPROCKHR":DataType.POINTER,
-}
-
-API_SPECS = [
-    ('GL2','../GLES2/gl2_api.in'),
-    ('GL2Ext','../GLES2/gl2ext_api.in'),
-    ('GL1','../GLES_CM/gl_api.in'),
-    ('GL1Ext','../GLES_CM/glext_api.in'),
-]
-
-HEADER_LICENSE = """/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- *
- * THIS FILE WAS GENERATED BY A SCRIPT. DO NOT EDIT.
- */
-"""
-
-HEADER_INCLUDES = """
-#include <cutils/log.h>
-#include <utils/Timers.h>
-
-#include "gltrace.pb.h"
-#include "gltrace_context.h"
-#include "gltrace_fixup.h"
-#include "gltrace_transport.h"
-"""
-
-HEADER_NAMESPACE_START = """
-namespace android {
-namespace gltrace {
-"""
-
-FOOTER_TEXT = """
-}; // namespace gltrace
-}; // namespace android
-"""
-
-TRACE_CALL_TEMPLATE = pyratemp.Template(
-"""$!retType!$ GLTrace_$!func!$($!inputArgList!$) {
-    GLMessage glmsg;
-    GLTraceContext *glContext = getGLTraceContext();
-
-    glmsg.set_function(GLMessage::$!func!$);
-<!--(if len(parsedArgs) > 0)-->
-    <!--(for argname, argtype in parsedArgs)-->
-
-    // copy argument $!argname!$
-    GLMessage_DataType *arg_$!argname!$ = glmsg.add_args();
-    arg_$!argname!$->set_isarray(false);
-    arg_$!argname!$->set_type(GLMessage::DataType::$!argtype!$);
-    arg_$!argname!$->$!argtype.getProtobufCall()!$$!argname!$);
-    <!--(end)-->
-<!--(end)-->
-
-    // call function
-    nsecs_t wallStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
-    nsecs_t threadStartTime = systemTime(SYSTEM_TIME_THREAD);
-<!--(if retType != "void")-->
-    $!retType!$ retValue = glContext->hooks->gl.$!callsite!$;
-<!--(else)-->
-    glContext->hooks->gl.$!callsite!$;
-<!--(end)-->
-    nsecs_t threadEndTime = systemTime(SYSTEM_TIME_THREAD);
-    nsecs_t wallEndTime = systemTime(SYSTEM_TIME_MONOTONIC);
-<!--(if retType != "void")-->
-
-    // set return value
-    GLMessage_DataType *rt = glmsg.mutable_returnvalue();
-    rt->set_isarray(false);
-    rt->set_type(GLMessage::DataType::$!retDataType!$);
-    rt->$!retDataType.getProtobufCall()!$retValue);
-<!--(end)-->
-
-    void *pointerArgs[] = {
-<!--(for argname, argtype in parsedArgs)-->
-    <!--(if argtype == DataType.POINTER)-->
-        (void *) $!argname!$,
-    <!--(end)-->
-<!--(end)-->
-<!--(if retDataType == DataType.POINTER)-->
-        (void *) retValue,
-<!--(end)-->
-    };
-
-    fixupGLMessage(glContext, wallStartTime, wallEndTime,
-                              threadStartTime, threadEndTime,
-                              &glmsg, pointerArgs);
-    glContext->traceGLMessage(&glmsg);
-<!--(if retType != "void")-->
-
-    return retValue;
-<!--(end)-->
-}
-""")
-
-def getDataTypeFromKw(kw):
-    """ Get the data type given declaration.
-    All pointer declarations are of type DataType.POINTER
-
-    e.g.: GLvoid -> DataType.VOID"""
-
-    if kw.count('*') > 0:
-        return DataType.POINTER
-    return GLPROTOBUF_TYPE_MAP.get(kw)
-
-def getNameTypePair(decl):
-    """ Split declaration of a variable to a tuple of (variable name, DataType).
-    e.g. "const GLChar* varName" -> (varName, POINTER) """
-    elements = decl.strip().split(' ')
-    name = None
-    if len(elements) > 1:
-        name = " ".join(elements[-1:]).strip()      # last element is the name
-        dataType = " ".join(elements[:-1]).strip()  # everything else is the data type
-
-        # if name is a pointer (e.g. "*ptr"), then remove the "*" from the name
-        # and add it to the data type
-        pointersInName = name.count("*")
-        if pointersInName > 0:
-            name = name.replace("*", "")
-            dataType += "*" * pointersInName
-
-        # if name is an array (e.g. "array[10]"), then remove the "[X]" from the name
-        # and make the datatype to be a pointer
-        arraysInName = name.count("[")
-        if arraysInName > 0:
-            name = name.split('[')[0]
-            dataType += "*"
-    else:
-        dataType = elements[0]
-    return (name, getDataTypeFromKw(dataType))
-
-def parseArgs(arglist):
-    """ Parse the argument list into a list of (var name, DataType) tuples """
-    args = arglist.split(',')
-    args = map(lambda x: x.strip(), args)    # remove unnecessary whitespaces
-    argtypelist = map(getNameTypePair, args) # split arg into arg type and arg name
-    if len(argtypelist) == 1:
-        (name, argtype) = argtypelist[0]
-        if argtype == DataType.VOID:
-            return []
-
-    return argtypelist
-
-class ApiCall(object):
-    """An ApiCall models all information about a single OpenGL API"""
-
-    # Regex to match API_ENTRY specification:
-    #       e.g. void API_ENTRY(glActiveTexture)(GLenum texture) {
-    # the regex uses a non greedy match (?) to match the first closing paren
-    API_ENTRY_REGEX = "(.*)API_ENTRY\(.*?\)\((.*?)\)"
-
-    # Regex to match CALL_GL_API specification:
-    #       e.g. CALL_GL_API(glCullFace, mode);
-    #            CALL_GL_API_RETURN(glCreateProgram);
-    CALL_GL_API_REGEX = "CALL_GL_API(_RETURN)?\((.*)\);"
-
-    def __init__(self, prefix, apientry, callsite):
-        """Construct an ApiCall from its specification.
-
-        The specification is provided by the two arguments:
-        prefix: prefix to use for function names
-        defn: specification line containing API_ENTRY macro
-              e.g: void API_ENTRY(glActiveTexture)(GLenum texture) {
-        callsite: specification line containing CALL_GL_API macro
-              e.g: CALL_GL_API(glActiveTexture, texture);
-        """
-        self.prefix = prefix
-        self.ret = self.getReturnType(apientry)
-        self.arglist = self.getArgList(apientry)
-
-        # some functions (e.g. __glEGLImageTargetRenderbufferStorageOES), define their
-        # names one way in the API_ENTRY and another way in the CALL_GL_API macros.
-        # so self.func is reassigned based on what is there in the call site
-        self.func = self.getFunc(callsite)
-        self.callsite = self.getCallSite(callsite)
-
-    def getReturnType(self, apientry):
-        '''Extract the return type from the API_ENTRY specification'''
-        m = re.search(self.API_ENTRY_REGEX, apientry)
-        if not m:
-            raise ValueError("%s does not match API_ENTRY specification %s"
-                             % (apientry, self.API_ENTRY_REGEX))
-
-        return m.group(1).strip()
-
-    def getArgList(self, apientry):
-        '''Extract the argument list from the API_ENTRY specification'''
-        m = re.search(self.API_ENTRY_REGEX, apientry)
-        if not m:
-            raise ValueError("%s does not match API_ENTRY specification %s"
-                             % (apientry, self.API_ENTRY_REGEX))
-
-        return m.group(2).strip()
-
-    def parseCallSite(self, callsite):
-        m = re.search(self.CALL_GL_API_REGEX, callsite)
-        if not m:
-            raise ValueError("%s does not match CALL_GL_API specification (%s)"
-                             % (callsite, self.CALL_GL_API_REGEX))
-
-        arglist = m.group(2)
-        args = arglist.split(',')
-        args = map(lambda x: x.strip(), args)
-
-        return args
-
-    def getCallSite(self, callsite):
-        '''Extract the callsite from the CALL_GL_API specification'''
-        args = self.parseCallSite(callsite)
-        return "%s(%s)" % (args[0], ", ".join(args[1:]))
-
-    def getFunc(self, callsite):
-        '''Extract the function name from the CALL_GL_API specification'''
-        args = self.parseCallSite(callsite)
-        return args[0]
-
-    def genDeclaration(self):
-        return "%s GLTrace_%s(%s);" % (self.ret, self.func, self.arglist)
-
-    def genCode(self):
-        return TRACE_CALL_TEMPLATE(func = self.func,
-                                   retType = self.ret,
-                                   retDataType = getDataTypeFromKw(self.ret),
-                                   inputArgList = self.arglist,
-                                   callsite = self.callsite,
-                                   parsedArgs = parseArgs(self.arglist),
-                                   DataType=DataType)
-
-def getApis(apiEntryFile, prefix):
-    '''Get a list of all ApiCalls in provided specification file'''
-    lines = open(apiEntryFile).readlines()
-
-    apis = []
-    for i in range(0, len(lines)/3):
-        apis.append(ApiCall(prefix, lines[i*3], lines[i*3+1]))
-
-    return apis
-
-def parseAllSpecs(specs):
-    apis = []
-    for name, specfile in specs:
-        a = getApis(specfile, name)
-        print 'Parsed %s APIs from %s, # of entries = %d' % (name, specfile, len(a))
-        apis.extend(a)
-    return apis
-
-def removeDuplicates(apis):
-    '''Remove all duplicate function entries.
-
-    The input list contains functions declared in GL1, GL2, and GL3 APIs.
-    This will return a list that contains only the first function if there are
-    multiple functions with the same name.'''
-    uniqs = []
-    funcs = set()
-    for api in apis:
-        if api.func not in funcs:
-            uniqs.append(api)
-            funcs.add(api.func)
-
-    return uniqs
-
-def genHeaders(apis, fname):
-    lines = []
-    lines.append(HEADER_LICENSE)
-    lines.append(HEADER_NAMESPACE_START)
-    prefix = ""
-    for api in apis:
-        if prefix != api.prefix:
-            lines.append("\n// Declarations for %s APIs\n\n" % api.prefix)
-            prefix = api.prefix
-        lines.append(api.genDeclaration())
-        lines.append("\n")
-    lines.append(FOOTER_TEXT)
-
-    with open(fname, "w") as f:
-        f.writelines(lines)
-
-def genSrcs(apis, fname):
-    lines = []
-    lines.append(HEADER_LICENSE)
-    lines.append(HEADER_INCLUDES)
-    lines.append(HEADER_NAMESPACE_START)
-    prefix = ""
-    for api in apis:
-        if prefix != api.prefix:
-            lines.append("\n// Definitions for %s APIs\n\n" % api.prefix)
-            prefix = api.prefix
-        lines.append(api.genCode())
-        lines.append("\n")
-    lines.append(FOOTER_TEXT)
-
-    with open(fname, "w") as f:
-        f.writelines(lines)
-
-if __name__ == '__main__':
-    apis = parseAllSpecs(API_SPECS)    # read in all the specfiles
-    apis = removeDuplicates(apis)      # remove duplication of functions common to multiple versions
-    genHeaders(apis, 'gltrace_api.h')  # generate header file
-    genSrcs(apis, 'gltrace_api.cpp')   # generate source file
diff --git a/opengl/libs/GLES_trace/tools/testgenapi.py b/opengl/libs/GLES_trace/tools/testgenapi.py
deleted file mode 100644
index fe14954..0000000
--- a/opengl/libs/GLES_trace/tools/testgenapi.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2011 Google 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.
-#
-# USAGE
-#   $ cd GLES_trace/tools
-#   $ python testgenapi.py
-
-import unittest
-from genapi import DataType, ApiCall, getApis, parseArgs
-
-class TestApiCall(unittest.TestCase):
-    def test_parsing(self):
-        apientry = 'void API_ENTRY(glCopyTexSubImage2D)(GLenum target, GLint level, ' \
-                   'GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, ' \
-                   'GLsizei height) {'
-        callsite = 'CALL_GL_API(glCopyTexImage2D, target, level, internalformat, x, y,' \
-                   'width, height, border);'
-
-        api = ApiCall("GL", apientry, callsite)
-        self.assertEqual(api.func, "glCopyTexImage2D")
-        self.assertEqual(api.callsite, 'glCopyTexImage2D(target, level, internalformat, ' \
-                                        'x, y, width, height, border)')
-        self.assertEqual(api.ret, 'void')
-        self.assertEqual(api.arglist, 'GLenum target, GLint level, ' \
-                   'GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, ' \
-                   'GLsizei height')
-
-    def test_num_functions_parsed(self):
-        gl2_apis = getApis('../../GLES2/gl2_api.in', 'GL2')
-        gl2ext_apis = getApis('../../GLES2/gl2ext_api.in', 'GL2Ext')
-        gl_apis = getApis('../../GLES_CM/gl_api.in', "GL1")
-        glext_apis = getApis('../../GLES_CM/glext_api.in', 'GL1Ext')
-
-        self.assertEqual(len(gl2_apis), 142)
-        self.assertEqual(len(gl2ext_apis), 121)
-        self.assertEqual(len(gl_apis), 145)
-        self.assertEqual(len(glext_apis), 140)
-
-    def test_parseArgs(self):
-        args = parseArgs("void")
-        self.assertEqual(len(args), 0)
-
-        args = parseArgs("GLchar a")
-        self.assertEqual(args, [("a", DataType.CHAR)])
-
-        args = parseArgs("GLchar *a")
-        self.assertEqual(args, [("a", DataType.POINTER)])
-
-        args = parseArgs("GLint exponent[16]")
-        self.assertEqual(args, [("exponent", DataType.POINTER)])
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/opengl/libs/entries.in b/opengl/libs/entries.in
index 0dee45d..e3b7cf3 100644
--- a/opengl/libs/entries.in
+++ b/opengl/libs/entries.in
@@ -5,16 +5,20 @@
 GL_ENTRY(void, glAlphaFuncQCOM, GLenum func, GLclampf ref)
 GL_ENTRY(void, glAlphaFuncx, GLenum func, GLfixed ref)
 GL_ENTRY(void, glAlphaFuncxOES, GLenum func, GLfixed ref)
+GL_ENTRY(void, glApplyFramebufferAttachmentCMAAINTEL, void)
 GL_ENTRY(void, glAttachShader, GLuint program, GLuint shader)
+GL_ENTRY(void, glBeginConditionalRenderNV, GLuint id, GLenum mode)
 GL_ENTRY(void, glBeginPerfMonitorAMD, GLuint monitor)
 GL_ENTRY(void, glBeginPerfQueryINTEL, GLuint queryHandle)
 GL_ENTRY(void, glBeginQuery, GLenum target, GLuint id)
 GL_ENTRY(void, glBeginQueryEXT, GLenum target, GLuint id)
 GL_ENTRY(void, glBeginTransformFeedback, GLenum primitiveMode)
-GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar * name)
+GL_ENTRY(void, glBindAttribLocation, GLuint program, GLuint index, const GLchar *name)
 GL_ENTRY(void, glBindBuffer, GLenum target, GLuint buffer)
 GL_ENTRY(void, glBindBufferBase, GLenum target, GLuint index, GLuint buffer)
 GL_ENTRY(void, glBindBufferRange, GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+GL_ENTRY(void, glBindFragDataLocationEXT, GLuint program, GLuint color, const GLchar *name)
+GL_ENTRY(void, glBindFragDataLocationIndexedEXT, GLuint program, GLuint colorNumber, GLuint index, const GLchar *name)
 GL_ENTRY(void, glBindFramebuffer, GLenum target, GLuint framebuffer)
 GL_ENTRY(void, glBindFramebufferOES, GLenum target, GLuint framebuffer)
 GL_ENTRY(void, glBindImageTexture, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format)
@@ -28,6 +32,7 @@
 GL_ENTRY(void, glBindVertexArray, GLuint array)
 GL_ENTRY(void, glBindVertexArrayOES, GLuint array)
 GL_ENTRY(void, glBindVertexBuffer, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride)
+GL_ENTRY(void, glBlendBarrier, void)
 GL_ENTRY(void, glBlendBarrierKHR, void)
 GL_ENTRY(void, glBlendBarrierNV, void)
 GL_ENTRY(void, glBlendColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
@@ -35,26 +40,35 @@
 GL_ENTRY(void, glBlendEquationOES, GLenum mode)
 GL_ENTRY(void, glBlendEquationSeparate, GLenum modeRGB, GLenum modeAlpha)
 GL_ENTRY(void, glBlendEquationSeparateOES, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparatei, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
 GL_ENTRY(void, glBlendEquationSeparateiEXT, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationSeparateiOES, GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+GL_ENTRY(void, glBlendEquationi, GLuint buf, GLenum mode)
 GL_ENTRY(void, glBlendEquationiEXT, GLuint buf, GLenum mode)
+GL_ENTRY(void, glBlendEquationiOES, GLuint buf, GLenum mode)
 GL_ENTRY(void, glBlendFunc, GLenum sfactor, GLenum dfactor)
 GL_ENTRY(void, glBlendFuncSeparate, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
 GL_ENTRY(void, glBlendFuncSeparateOES, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
 GL_ENTRY(void, glBlendFuncSeparateiEXT, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFuncSeparateiOES, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+GL_ENTRY(void, glBlendFunci, GLuint buf, GLenum src, GLenum dst)
 GL_ENTRY(void, glBlendFunciEXT, GLuint buf, GLenum src, GLenum dst)
+GL_ENTRY(void, glBlendFunciOES, GLuint buf, GLenum src, GLenum dst)
 GL_ENTRY(void, glBlendParameteriNV, GLenum pname, GLint value)
 GL_ENTRY(void, glBlitFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
 GL_ENTRY(void, glBlitFramebufferANGLE, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
 GL_ENTRY(void, glBlitFramebufferNV, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
-GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void * data, GLenum usage)
-GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void * data)
+GL_ENTRY(void, glBufferData, GLenum target, GLsizeiptr size, const void *data, GLenum usage)
+GL_ENTRY(void, glBufferStorageEXT, GLenum target, GLsizeiptr size, const void *data, GLbitfield flags)
+GL_ENTRY(void, glBufferSubData, GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
 GL_ENTRY(GLenum, glCheckFramebufferStatus, GLenum target)
 GL_ENTRY(GLenum, glCheckFramebufferStatusOES, GLenum target)
 GL_ENTRY(void, glClear, GLbitfield mask)
 GL_ENTRY(void, glClearBufferfi, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
-GL_ENTRY(void, glClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat * value)
-GL_ENTRY(void, glClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint * value)
-GL_ENTRY(void, glClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint * value)
+GL_ENTRY(void, glClearBufferfv, GLenum buffer, GLint drawbuffer, const GLfloat *value)
+GL_ENTRY(void, glClearBufferiv, GLenum buffer, GLint drawbuffer, const GLint *value)
+GL_ENTRY(void, glClearBufferuiv, GLenum buffer, GLint drawbuffer, const GLuint *value)
 GL_ENTRY(void, glClearColor, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
 GL_ENTRY(void, glClearColorx, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
 GL_ENTRY(void, glClearColorxOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
@@ -66,69 +80,86 @@
 GL_ENTRY(void, glClientActiveTexture, GLenum texture)
 GL_ENTRY(GLenum, glClientWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout)
 GL_ENTRY(GLenum, glClientWaitSyncAPPLE, GLsync sync, GLbitfield flags, GLuint64 timeout)
-GL_ENTRY(void, glClipPlanef, GLenum p, const GLfloat * eqn)
-GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat * eqn)
-GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat * equation)
-GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed * equation)
-GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed * eqn)
-GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed * equation)
+GL_ENTRY(void, glClipPlanef, GLenum p, const GLfloat *eqn)
+GL_ENTRY(void, glClipPlanefIMG, GLenum p, const GLfloat *eqn)
+GL_ENTRY(void, glClipPlanefOES, GLenum plane, const GLfloat *equation)
+GL_ENTRY(void, glClipPlanex, GLenum plane, const GLfixed *equation)
+GL_ENTRY(void, glClipPlanexIMG, GLenum p, const GLfixed *eqn)
+GL_ENTRY(void, glClipPlanexOES, GLenum plane, const GLfixed *equation)
 GL_ENTRY(void, glColor4f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
 GL_ENTRY(void, glColor4ub, GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
 GL_ENTRY(void, glColor4x, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
 GL_ENTRY(void, glColor4xOES, GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
 GL_ENTRY(void, glColorMask, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+GL_ENTRY(void, glColorMaski, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
 GL_ENTRY(void, glColorMaskiEXT, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
-GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glColorMaskiOES, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+GL_ENTRY(void, glColorPointer, GLint size, GLenum type, GLsizei stride, const void *pointer)
 GL_ENTRY(void, glCompileShader, GLuint shader)
-GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data)
-GL_ENTRY(void, glCompressedTexImage3D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data)
-GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data)
-GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data)
-GL_ENTRY(void, glCompressedTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data)
-GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data)
+GL_ENTRY(void, glCompressedTexImage2D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexImage3D, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
+GL_ENTRY(void, glCompressedTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data)
 GL_ENTRY(void, glCopyBufferSubData, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
 GL_ENTRY(void, glCopyBufferSubDataNV, GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+GL_ENTRY(void, glCopyImageSubData, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
 GL_ENTRY(void, glCopyImageSubDataEXT, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+GL_ENTRY(void, glCopyImageSubDataOES, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+GL_ENTRY(void, glCopyPathNV, GLuint resultPath, GLuint srcPath)
 GL_ENTRY(void, glCopyTexImage2D, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
 GL_ENTRY(void, glCopyTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 GL_ENTRY(void, glCopyTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 GL_ENTRY(void, glCopyTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
 GL_ENTRY(void, glCopyTextureLevelsAPPLE, GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount)
+GL_ENTRY(void, glCoverFillPathInstancedNV, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues)
+GL_ENTRY(void, glCoverFillPathNV, GLuint path, GLenum coverMode)
+GL_ENTRY(void, glCoverStrokePathInstancedNV, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues)
+GL_ENTRY(void, glCoverStrokePathNV, GLuint path, GLenum coverMode)
 GL_ENTRY(void, glCoverageMaskNV, GLboolean mask)
+GL_ENTRY(void, glCoverageModulationNV, GLenum components)
+GL_ENTRY(void, glCoverageModulationTableNV, GLsizei n, const GLfloat *v)
 GL_ENTRY(void, glCoverageOperationNV, GLenum operation)
-GL_ENTRY(void, glCreatePerfQueryINTEL, GLuint queryId, GLuint * queryHandle)
+GL_ENTRY(void, glCreatePerfQueryINTEL, GLuint queryId, GLuint *queryHandle)
 GL_ENTRY(GLuint, glCreateProgram, void)
 GL_ENTRY(GLuint, glCreateShader, GLenum type)
-GL_ENTRY(GLuint, glCreateShaderProgramv, GLenum type, GLsizei count, const GLchar *const* strings)
-GL_ENTRY(GLuint, glCreateShaderProgramvEXT, GLenum type, GLsizei count, const GLchar ** strings)
+GL_ENTRY(GLuint, glCreateShaderProgramv, GLenum type, GLsizei count, const GLchar *const*strings)
+GL_ENTRY(GLuint, glCreateShaderProgramvEXT, GLenum type, GLsizei count, const GLchar **strings)
 GL_ENTRY(void, glCullFace, GLenum mode)
 GL_ENTRY(void, glCurrentPaletteMatrixOES, GLuint matrixpaletteindex)
-GL_ENTRY(void, glDebugMessageCallbackKHR, GLDEBUGPROCKHR callback, const void * userParam)
-GL_ENTRY(void, glDebugMessageControlKHR, GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled)
-GL_ENTRY(void, glDebugMessageInsertKHR, GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf)
-GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint * buffers)
-GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint * fences)
-GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint * framebuffers)
-GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint * framebuffers)
-GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint * monitors)
+GL_ENTRY(void, glDebugMessageCallback, GLDEBUGPROC callback, const void *userParam)
+GL_ENTRY(void, glDebugMessageCallbackKHR, GLDEBUGPROCKHR callback, const void *userParam)
+GL_ENTRY(void, glDebugMessageControl, GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)
+GL_ENTRY(void, glDebugMessageControlKHR, GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled)
+GL_ENTRY(void, glDebugMessageInsert, GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf)
+GL_ENTRY(void, glDebugMessageInsertKHR, GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf)
+GL_ENTRY(void, glDeleteBuffers, GLsizei n, const GLuint *buffers)
+GL_ENTRY(void, glDeleteFencesNV, GLsizei n, const GLuint *fences)
+GL_ENTRY(void, glDeleteFramebuffers, GLsizei n, const GLuint *framebuffers)
+GL_ENTRY(void, glDeleteFramebuffersOES, GLsizei n, const GLuint *framebuffers)
+GL_ENTRY(void, glDeletePathsNV, GLuint path, GLsizei range)
+GL_ENTRY(void, glDeletePerfMonitorsAMD, GLsizei n, GLuint *monitors)
 GL_ENTRY(void, glDeletePerfQueryINTEL, GLuint queryHandle)
 GL_ENTRY(void, glDeleteProgram, GLuint program)
-GL_ENTRY(void, glDeleteProgramPipelines, GLsizei n, const GLuint * pipelines)
-GL_ENTRY(void, glDeleteProgramPipelinesEXT, GLsizei n, const GLuint * pipelines)
-GL_ENTRY(void, glDeleteQueries, GLsizei n, const GLuint * ids)
-GL_ENTRY(void, glDeleteQueriesEXT, GLsizei n, const GLuint * ids)
-GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint * renderbuffers)
-GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint * renderbuffers)
-GL_ENTRY(void, glDeleteSamplers, GLsizei count, const GLuint * samplers)
+GL_ENTRY(void, glDeleteProgramPipelines, GLsizei n, const GLuint *pipelines)
+GL_ENTRY(void, glDeleteProgramPipelinesEXT, GLsizei n, const GLuint *pipelines)
+GL_ENTRY(void, glDeleteQueries, GLsizei n, const GLuint *ids)
+GL_ENTRY(void, glDeleteQueriesEXT, GLsizei n, const GLuint *ids)
+GL_ENTRY(void, glDeleteRenderbuffers, GLsizei n, const GLuint *renderbuffers)
+GL_ENTRY(void, glDeleteRenderbuffersOES, GLsizei n, const GLuint *renderbuffers)
+GL_ENTRY(void, glDeleteSamplers, GLsizei count, const GLuint *samplers)
 GL_ENTRY(void, glDeleteShader, GLuint shader)
 GL_ENTRY(void, glDeleteSync, GLsync sync)
 GL_ENTRY(void, glDeleteSyncAPPLE, GLsync sync)
-GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint * textures)
-GL_ENTRY(void, glDeleteTransformFeedbacks, GLsizei n, const GLuint * ids)
-GL_ENTRY(void, glDeleteVertexArrays, GLsizei n, const GLuint * arrays)
-GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint * arrays)
+GL_ENTRY(void, glDeleteTextures, GLsizei n, const GLuint *textures)
+GL_ENTRY(void, glDeleteTransformFeedbacks, GLsizei n, const GLuint *ids)
+GL_ENTRY(void, glDeleteVertexArrays, GLsizei n, const GLuint *arrays)
+GL_ENTRY(void, glDeleteVertexArraysOES, GLsizei n, const GLuint *arrays)
 GL_ENTRY(void, glDepthFunc, GLenum func)
 GL_ENTRY(void, glDepthMask, GLboolean flag)
+GL_ENTRY(void, glDepthRangeArrayfvNV, GLuint first, GLsizei count, const GLfloat *v)
+GL_ENTRY(void, glDepthRangeIndexedfNV, GLuint index, GLfloat n, GLfloat f)
 GL_ENTRY(void, glDepthRangef, GLfloat n, GLfloat f)
 GL_ENTRY(void, glDepthRangefOES, GLclampf n, GLclampf f)
 GL_ENTRY(void, glDepthRangex, GLfixed n, GLfixed f)
@@ -138,58 +169,77 @@
 GL_ENTRY(void, glDisableClientState, GLenum array)
 GL_ENTRY(void, glDisableDriverControlQCOM, GLuint driverControl)
 GL_ENTRY(void, glDisableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glDisablei, GLenum target, GLuint index)
 GL_ENTRY(void, glDisableiEXT, GLenum target, GLuint index)
-GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum * attachments)
+GL_ENTRY(void, glDisableiNV, GLenum target, GLuint index)
+GL_ENTRY(void, glDisableiOES, GLenum target, GLuint index)
+GL_ENTRY(void, glDiscardFramebufferEXT, GLenum target, GLsizei numAttachments, const GLenum *attachments)
 GL_ENTRY(void, glDispatchCompute, GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
 GL_ENTRY(void, glDispatchComputeIndirect, GLintptr indirect)
 GL_ENTRY(void, glDrawArrays, GLenum mode, GLint first, GLsizei count)
-GL_ENTRY(void, glDrawArraysIndirect, GLenum mode, const void * indirect)
+GL_ENTRY(void, glDrawArraysIndirect, GLenum mode, const void *indirect)
 GL_ENTRY(void, glDrawArraysInstanced, GLenum mode, GLint first, GLsizei count, GLsizei instancecount)
 GL_ENTRY(void, glDrawArraysInstancedANGLE, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+GL_ENTRY(void, glDrawArraysInstancedBaseInstanceEXT, GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance)
 GL_ENTRY(void, glDrawArraysInstancedEXT, GLenum mode, GLint start, GLsizei count, GLsizei primcount)
 GL_ENTRY(void, glDrawArraysInstancedNV, GLenum mode, GLint first, GLsizei count, GLsizei primcount)
-GL_ENTRY(void, glDrawBuffers, GLsizei n, const GLenum * bufs)
-GL_ENTRY(void, glDrawBuffersEXT, GLsizei n, const GLenum * bufs)
-GL_ENTRY(void, glDrawBuffersIndexedEXT, GLint n, const GLenum * location, const GLint * indices)
-GL_ENTRY(void, glDrawBuffersNV, GLsizei n, const GLenum * bufs)
-GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void * indices)
-GL_ENTRY(void, glDrawElementsIndirect, GLenum mode, GLenum type, const void * indirect)
-GL_ENTRY(void, glDrawElementsInstanced, GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount)
-GL_ENTRY(void, glDrawElementsInstancedANGLE, GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount)
-GL_ENTRY(void, glDrawElementsInstancedEXT, GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount)
-GL_ENTRY(void, glDrawElementsInstancedNV, GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount)
-GL_ENTRY(void, glDrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices)
+GL_ENTRY(void, glDrawBuffers, GLsizei n, const GLenum *bufs)
+GL_ENTRY(void, glDrawBuffersEXT, GLsizei n, const GLenum *bufs)
+GL_ENTRY(void, glDrawBuffersIndexedEXT, GLint n, const GLenum *location, const GLint *indices)
+GL_ENTRY(void, glDrawBuffersNV, GLsizei n, const GLenum *bufs)
+GL_ENTRY(void, glDrawElements, GLenum mode, GLsizei count, GLenum type, const void *indices)
+GL_ENTRY(void, glDrawElementsBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawElementsBaseVertexEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawElementsBaseVertexOES, GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawElementsIndirect, GLenum mode, GLenum type, const void *indirect)
+GL_ENTRY(void, glDrawElementsInstanced, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount)
+GL_ENTRY(void, glDrawElementsInstancedANGLE, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount)
+GL_ENTRY(void, glDrawElementsInstancedBaseInstanceEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertex, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertexBaseInstanceEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertexEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
+GL_ENTRY(void, glDrawElementsInstancedBaseVertexOES, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex)
+GL_ENTRY(void, glDrawElementsInstancedEXT, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount)
+GL_ENTRY(void, glDrawElementsInstancedNV, GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount)
+GL_ENTRY(void, glDrawRangeElements, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices)
+GL_ENTRY(void, glDrawRangeElementsBaseVertex, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawRangeElementsBaseVertexEXT, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
+GL_ENTRY(void, glDrawRangeElementsBaseVertexOES, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex)
 GL_ENTRY(void, glDrawTexfOES, GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height)
-GL_ENTRY(void, glDrawTexfvOES, const GLfloat * coords)
+GL_ENTRY(void, glDrawTexfvOES, const GLfloat *coords)
 GL_ENTRY(void, glDrawTexiOES, GLint x, GLint y, GLint z, GLint width, GLint height)
-GL_ENTRY(void, glDrawTexivOES, const GLint * coords)
+GL_ENTRY(void, glDrawTexivOES, const GLint *coords)
 GL_ENTRY(void, glDrawTexsOES, GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
-GL_ENTRY(void, glDrawTexsvOES, const GLshort * coords)
+GL_ENTRY(void, glDrawTexsvOES, const GLshort *coords)
 GL_ENTRY(void, glDrawTexxOES, GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
-GL_ENTRY(void, glDrawTexxvOES, const GLfixed * coords)
+GL_ENTRY(void, glDrawTexxvOES, const GLfixed *coords)
 GL_ENTRY(void, glEGLImageTargetRenderbufferStorageOES, GLenum target, GLeglImageOES image)
 GL_ENTRY(void, glEGLImageTargetTexture2DOES, GLenum target, GLeglImageOES image)
 GL_ENTRY(void, glEnable, GLenum cap)
 GL_ENTRY(void, glEnableClientState, GLenum array)
 GL_ENTRY(void, glEnableDriverControlQCOM, GLuint driverControl)
 GL_ENTRY(void, glEnableVertexAttribArray, GLuint index)
+GL_ENTRY(void, glEnablei, GLenum target, GLuint index)
 GL_ENTRY(void, glEnableiEXT, GLenum target, GLuint index)
+GL_ENTRY(void, glEnableiNV, GLenum target, GLuint index)
+GL_ENTRY(void, glEnableiOES, GLenum target, GLuint index)
+GL_ENTRY(void, glEndConditionalRenderNV, void)
 GL_ENTRY(void, glEndPerfMonitorAMD, GLuint monitor)
 GL_ENTRY(void, glEndPerfQueryINTEL, GLuint queryHandle)
 GL_ENTRY(void, glEndQuery, GLenum target)
 GL_ENTRY(void, glEndQueryEXT, GLenum target)
 GL_ENTRY(void, glEndTilingQCOM, GLbitfield preserveMask)
 GL_ENTRY(void, glEndTransformFeedback, void)
-GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, void ** params)
-GL_ENTRY(void, glExtGetBuffersQCOM, GLuint * buffers, GLint maxBuffers, GLint * numBuffers)
-GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint * framebuffers, GLint maxFramebuffers, GLint * numFramebuffers)
-GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar * source, GLint * length)
-GL_ENTRY(void, glExtGetProgramsQCOM, GLuint * programs, GLint maxPrograms, GLint * numPrograms)
-GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint * renderbuffers, GLint maxRenderbuffers, GLint * numRenderbuffers)
-GL_ENTRY(void, glExtGetShadersQCOM, GLuint * shaders, GLint maxShaders, GLint * numShaders)
-GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint * params)
-GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void * texels)
-GL_ENTRY(void, glExtGetTexturesQCOM, GLuint * textures, GLint maxTextures, GLint * numTextures)
+GL_ENTRY(void, glExtGetBufferPointervQCOM, GLenum target, void **params)
+GL_ENTRY(void, glExtGetBuffersQCOM, GLuint *buffers, GLint maxBuffers, GLint *numBuffers)
+GL_ENTRY(void, glExtGetFramebuffersQCOM, GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers)
+GL_ENTRY(void, glExtGetProgramBinarySourceQCOM, GLuint program, GLenum shadertype, GLchar *source, GLint *length)
+GL_ENTRY(void, glExtGetProgramsQCOM, GLuint *programs, GLint maxPrograms, GLint *numPrograms)
+GL_ENTRY(void, glExtGetRenderbuffersQCOM, GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers)
+GL_ENTRY(void, glExtGetShadersQCOM, GLuint *shaders, GLint maxShaders, GLint *numShaders)
+GL_ENTRY(void, glExtGetTexLevelParameterivQCOM, GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glExtGetTexSubImageQCOM, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels)
+GL_ENTRY(void, glExtGetTexturesQCOM, GLuint *textures, GLint maxTextures, GLint *numTextures)
 GL_ENTRY(GLboolean, glExtIsProgramBinaryQCOM, GLuint program)
 GL_ENTRY(void, glExtTexObjectStateOverrideiQCOM, GLenum target, GLenum pname, GLint param)
 GL_ENTRY(GLsync, glFenceSync, GLenum condition, GLbitfield flags)
@@ -200,14 +250,17 @@
 GL_ENTRY(void, glFlushMappedBufferRange, GLenum target, GLintptr offset, GLsizeiptr length)
 GL_ENTRY(void, glFlushMappedBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length)
 GL_ENTRY(void, glFogf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glFogfv, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glFogx, GLenum pname, GLfixed param)
 GL_ENTRY(void, glFogxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed * param)
-GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed * param)
+GL_ENTRY(void, glFogxv, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glFogxvOES, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glFragmentCoverageColorNV, GLuint color)
 GL_ENTRY(void, glFramebufferParameteri, GLenum target, GLenum pname, GLint param)
 GL_ENTRY(void, glFramebufferRenderbuffer, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
 GL_ENTRY(void, glFramebufferRenderbufferOES, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+GL_ENTRY(void, glFramebufferSampleLocationsfvNV, GLenum target, GLuint start, GLsizei count, const GLfloat *v)
+GL_ENTRY(void, glFramebufferTexture, GLenum target, GLenum attachment, GLuint texture, GLint level)
 GL_ENTRY(void, glFramebufferTexture2D, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
 GL_ENTRY(void, glFramebufferTexture2DMultisampleEXT, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
 GL_ENTRY(void, glFramebufferTexture2DMultisampleIMG, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples)
@@ -215,164 +268,213 @@
 GL_ENTRY(void, glFramebufferTexture3DOES, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset)
 GL_ENTRY(void, glFramebufferTextureEXT, GLenum target, GLenum attachment, GLuint texture, GLint level)
 GL_ENTRY(void, glFramebufferTextureLayer, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+GL_ENTRY(void, glFramebufferTextureMultisampleMultiviewOVR, GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews)
+GL_ENTRY(void, glFramebufferTextureMultiviewOVR, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews)
+GL_ENTRY(void, glFramebufferTextureOES, GLenum target, GLenum attachment, GLuint texture, GLint level)
 GL_ENTRY(void, glFrontFace, GLenum mode)
 GL_ENTRY(void, glFrustumf, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
 GL_ENTRY(void, glFrustumfOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
 GL_ENTRY(void, glFrustumx, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
 GL_ENTRY(void, glFrustumxOES, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
-GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint * buffers)
-GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint * fences)
-GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint * framebuffers)
-GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint * framebuffers)
-GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint * monitors)
-GL_ENTRY(void, glGenProgramPipelines, GLsizei n, GLuint * pipelines)
-GL_ENTRY(void, glGenProgramPipelinesEXT, GLsizei n, GLuint * pipelines)
-GL_ENTRY(void, glGenQueries, GLsizei n, GLuint * ids)
-GL_ENTRY(void, glGenQueriesEXT, GLsizei n, GLuint * ids)
-GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint * renderbuffers)
-GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint * renderbuffers)
-GL_ENTRY(void, glGenSamplers, GLsizei count, GLuint * samplers)
-GL_ENTRY(void, glGenTextures, GLsizei n, GLuint * textures)
-GL_ENTRY(void, glGenTransformFeedbacks, GLsizei n, GLuint * ids)
-GL_ENTRY(void, glGenVertexArrays, GLsizei n, GLuint * arrays)
-GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint * arrays)
+GL_ENTRY(void, glGenBuffers, GLsizei n, GLuint *buffers)
+GL_ENTRY(void, glGenFencesNV, GLsizei n, GLuint *fences)
+GL_ENTRY(void, glGenFramebuffers, GLsizei n, GLuint *framebuffers)
+GL_ENTRY(void, glGenFramebuffersOES, GLsizei n, GLuint *framebuffers)
+GL_ENTRY(GLuint, glGenPathsNV, GLsizei range)
+GL_ENTRY(void, glGenPerfMonitorsAMD, GLsizei n, GLuint *monitors)
+GL_ENTRY(void, glGenProgramPipelines, GLsizei n, GLuint *pipelines)
+GL_ENTRY(void, glGenProgramPipelinesEXT, GLsizei n, GLuint *pipelines)
+GL_ENTRY(void, glGenQueries, GLsizei n, GLuint *ids)
+GL_ENTRY(void, glGenQueriesEXT, GLsizei n, GLuint *ids)
+GL_ENTRY(void, glGenRenderbuffers, GLsizei n, GLuint *renderbuffers)
+GL_ENTRY(void, glGenRenderbuffersOES, GLsizei n, GLuint *renderbuffers)
+GL_ENTRY(void, glGenSamplers, GLsizei count, GLuint *samplers)
+GL_ENTRY(void, glGenTextures, GLsizei n, GLuint *textures)
+GL_ENTRY(void, glGenTransformFeedbacks, GLsizei n, GLuint *ids)
+GL_ENTRY(void, glGenVertexArrays, GLsizei n, GLuint *arrays)
+GL_ENTRY(void, glGenVertexArraysOES, GLsizei n, GLuint *arrays)
 GL_ENTRY(void, glGenerateMipmap, GLenum target)
 GL_ENTRY(void, glGenerateMipmapOES, GLenum target)
-GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)
-GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name)
-GL_ENTRY(void, glGetActiveUniformBlockName, GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName)
-GL_ENTRY(void, glGetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders)
-GL_ENTRY(GLint, glGetAttribLocation, GLuint program, const GLchar * name)
-GL_ENTRY(void, glGetBooleani_v, GLenum target, GLuint index, GLboolean * data)
-GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean * data)
-GL_ENTRY(void, glGetBufferParameteri64v, GLenum target, GLenum pname, GLint64 * params)
-GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetBufferPointerv, GLenum target, GLenum pname, void ** params)
-GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void ** params)
-GL_ENTRY(void, glGetClipPlanef, GLenum plane, GLfloat * equation)
-GL_ENTRY(void, glGetClipPlanefOES, GLenum plane, GLfloat * equation)
-GL_ENTRY(void, glGetClipPlanex, GLenum plane, GLfixed * equation)
-GL_ENTRY(void, glGetClipPlanexOES, GLenum plane, GLfixed * equation)
-GL_ENTRY(GLuint, glGetDebugMessageLogKHR, GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog)
-GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei * length, GLchar * driverControlString)
-GL_ENTRY(void, glGetDriverControlsQCOM, GLint * num, GLsizei size, GLuint * driverControls)
+GL_ENTRY(void, glGetActiveAttrib, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+GL_ENTRY(void, glGetActiveUniform, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+GL_ENTRY(void, glGetActiveUniformBlockName, GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName)
+GL_ENTRY(void, glGetActiveUniformBlockiv, GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetActiveUniformsiv, GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetAttachedShaders, GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders)
+GL_ENTRY(GLint, glGetAttribLocation, GLuint program, const GLchar *name)
+GL_ENTRY(void, glGetBooleani_v, GLenum target, GLuint index, GLboolean *data)
+GL_ENTRY(void, glGetBooleanv, GLenum pname, GLboolean *data)
+GL_ENTRY(void, glGetBufferParameteri64v, GLenum target, GLenum pname, GLint64 *params)
+GL_ENTRY(void, glGetBufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetBufferPointerv, GLenum target, GLenum pname, void **params)
+GL_ENTRY(void, glGetBufferPointervOES, GLenum target, GLenum pname, void **params)
+GL_ENTRY(void, glGetClipPlanef, GLenum plane, GLfloat *equation)
+GL_ENTRY(void, glGetClipPlanefOES, GLenum plane, GLfloat *equation)
+GL_ENTRY(void, glGetClipPlanex, GLenum plane, GLfixed *equation)
+GL_ENTRY(void, glGetClipPlanexOES, GLenum plane, GLfixed *equation)
+GL_ENTRY(void, glGetCoverageModulationTableNV, GLsizei bufsize, GLfloat *v)
+GL_ENTRY(GLuint, glGetDebugMessageLog, GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog)
+GL_ENTRY(GLuint, glGetDebugMessageLogKHR, GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog)
+GL_ENTRY(void, glGetDriverControlStringQCOM, GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString)
+GL_ENTRY(void, glGetDriverControlsQCOM, GLint *num, GLsizei size, GLuint *driverControls)
 GL_ENTRY(GLenum, glGetError, void)
-GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetFirstPerfQueryIdINTEL, GLuint * queryId)
-GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat * data)
-GL_ENTRY(GLint, glGetFragDataLocation, GLuint program, const GLchar * name)
-GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetFramebufferParameteriv, GLenum target, GLenum pname, GLint * params)
+GL_ENTRY(void, glGetFenceivNV, GLuint fence, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFirstPerfQueryIdINTEL, GLuint *queryId)
+GL_ENTRY(void, glGetFixedv, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFixedvOES, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetFloati_vNV, GLenum target, GLuint index, GLfloat *data)
+GL_ENTRY(void, glGetFloatv, GLenum pname, GLfloat *data)
+GL_ENTRY(GLint, glGetFragDataIndexEXT, GLuint program, const GLchar *name)
+GL_ENTRY(GLint, glGetFragDataLocation, GLuint program, const GLchar *name)
+GL_ENTRY(void, glGetFramebufferAttachmentParameteriv, GLenum target, GLenum attachment, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFramebufferAttachmentParameterivOES, GLenum target, GLenum attachment, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetFramebufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(GLenum, glGetGraphicsResetStatus, void)
 GL_ENTRY(GLenum, glGetGraphicsResetStatusEXT, void)
-GL_ENTRY(void, glGetInteger64i_v, GLenum target, GLuint index, GLint64 * data)
-GL_ENTRY(void, glGetInteger64v, GLenum pname, GLint64 * data)
-GL_ENTRY(void, glGetInteger64vAPPLE, GLenum pname, GLint64 * params)
-GL_ENTRY(void, glGetIntegeri_v, GLenum target, GLuint index, GLint * data)
-GL_ENTRY(void, glGetIntegeri_vEXT, GLenum target, GLuint index, GLint * data)
-GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint * data)
-GL_ENTRY(void, glGetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params)
-GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetMultisamplefv, GLenum pname, GLuint index, GLfloat * val)
-GL_ENTRY(void, glGetNextPerfQueryIdINTEL, GLuint queryId, GLuint * nextQueryId)
-GL_ENTRY(void, glGetObjectLabelEXT, GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label)
-GL_ENTRY(void, glGetObjectLabelKHR, GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label)
-GL_ENTRY(void, glGetObjectPtrLabelKHR, const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label)
-GL_ENTRY(void, glGetPerfCounterInfoINTEL, GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar * counterName, GLuint counterDescLength, GLchar * counterDesc, GLuint * counterOffset, GLuint * counterDataSize, GLuint * counterTypeEnum, GLuint * counterDataTypeEnum, GLuint64 * rawCounterMaxValue)
-GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint * data, GLint * bytesWritten)
-GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void * data)
-GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei * length, GLchar * counterString)
-GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint * numCounters, GLint * maxActiveCounters, GLsizei counterSize, GLuint * counters)
-GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei * length, GLchar * groupString)
-GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint * numGroups, GLsizei groupsSize, GLuint * groups)
-GL_ENTRY(void, glGetPerfQueryDataINTEL, GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid * data, GLuint * bytesWritten)
-GL_ENTRY(void, glGetPerfQueryIdByNameINTEL, GLchar * queryName, GLuint * queryId)
-GL_ENTRY(void, glGetPerfQueryInfoINTEL, GLuint queryId, GLuint queryNameLength, GLchar * queryName, GLuint * dataSize, GLuint * noCounters, GLuint * noInstances, GLuint * capsMask)
-GL_ENTRY(void, glGetPointerv, GLenum pname, void ** params)
-GL_ENTRY(void, glGetPointervKHR, GLenum pname, void ** params)
-GL_ENTRY(void, glGetProgramBinary, GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary)
-GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary)
-GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog)
-GL_ENTRY(void, glGetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog)
-GL_ENTRY(void, glGetProgramPipelineInfoLogEXT, GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog)
-GL_ENTRY(void, glGetProgramPipelineiv, GLuint pipeline, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetProgramPipelineivEXT, GLuint pipeline, GLenum pname, GLint * params)
-GL_ENTRY(GLuint, glGetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar * name)
-GL_ENTRY(GLint, glGetProgramResourceLocation, GLuint program, GLenum programInterface, const GLchar * name)
-GL_ENTRY(void, glGetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name)
-GL_ENTRY(void, glGetProgramResourceiv, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params)
-GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64 * params)
-GL_ENTRY(void, glGetQueryObjectivEXT, GLuint id, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64 * params)
-GL_ENTRY(void, glGetQueryObjectuiv, GLuint id, GLenum pname, GLuint * params)
-GL_ENTRY(void, glGetQueryObjectuivEXT, GLuint id, GLenum pname, GLuint * params)
-GL_ENTRY(void, glGetQueryiv, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetQueryivEXT, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetSamplerParameterIivEXT, GLuint sampler, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetSamplerParameterIuivEXT, GLuint sampler, GLenum pname, GLuint * params)
-GL_ENTRY(void, glGetSamplerParameterfv, GLuint sampler, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetSamplerParameteriv, GLuint sampler, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog)
-GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision)
-GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source)
-GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint * params)
+GL_ENTRY(GLenum, glGetGraphicsResetStatusKHR, void)
+GL_ENTRY(GLuint64, glGetImageHandleNV, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format)
+GL_ENTRY(void, glGetInteger64i_v, GLenum target, GLuint index, GLint64 *data)
+GL_ENTRY(void, glGetInteger64v, GLenum pname, GLint64 *data)
+GL_ENTRY(void, glGetInteger64vAPPLE, GLenum pname, GLint64 *params)
+GL_ENTRY(void, glGetIntegeri_v, GLenum target, GLuint index, GLint *data)
+GL_ENTRY(void, glGetIntegeri_vEXT, GLenum target, GLuint index, GLint *data)
+GL_ENTRY(void, glGetIntegerv, GLenum pname, GLint *data)
+GL_ENTRY(void, glGetInternalformatSampleivNV, GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetInternalformativ, GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetLightfv, GLenum light, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetLightxv, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetLightxvOES, GLenum light, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialfv, GLenum face, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetMaterialxv, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMaterialxvOES, GLenum face, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetMultisamplefv, GLenum pname, GLuint index, GLfloat *val)
+GL_ENTRY(void, glGetNextPerfQueryIdINTEL, GLuint queryId, GLuint *nextQueryId)
+GL_ENTRY(void, glGetObjectLabel, GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetObjectLabelEXT, GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetObjectLabelKHR, GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetObjectPtrLabel, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetObjectPtrLabelKHR, const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label)
+GL_ENTRY(void, glGetPathCommandsNV, GLuint path, GLubyte *commands)
+GL_ENTRY(void, glGetPathCoordsNV, GLuint path, GLfloat *coords)
+GL_ENTRY(void, glGetPathDashArrayNV, GLuint path, GLfloat *dashArray)
+GL_ENTRY(GLfloat, glGetPathLengthNV, GLuint path, GLsizei startSegment, GLsizei numSegments)
+GL_ENTRY(void, glGetPathMetricRangeNV, GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics)
+GL_ENTRY(void, glGetPathMetricsNV, GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics)
+GL_ENTRY(void, glGetPathParameterfvNV, GLuint path, GLenum pname, GLfloat *value)
+GL_ENTRY(void, glGetPathParameterivNV, GLuint path, GLenum pname, GLint *value)
+GL_ENTRY(void, glGetPathSpacingNV, GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing)
+GL_ENTRY(void, glGetPerfCounterInfoINTEL, GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue)
+GL_ENTRY(void, glGetPerfMonitorCounterDataAMD, GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten)
+GL_ENTRY(void, glGetPerfMonitorCounterInfoAMD, GLuint group, GLuint counter, GLenum pname, void *data)
+GL_ENTRY(void, glGetPerfMonitorCounterStringAMD, GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString)
+GL_ENTRY(void, glGetPerfMonitorCountersAMD, GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters)
+GL_ENTRY(void, glGetPerfMonitorGroupStringAMD, GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString)
+GL_ENTRY(void, glGetPerfMonitorGroupsAMD, GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+GL_ENTRY(void, glGetPerfQueryDataINTEL, GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten)
+GL_ENTRY(void, glGetPerfQueryIdByNameINTEL, GLchar *queryName, GLuint *queryId)
+GL_ENTRY(void, glGetPerfQueryInfoINTEL, GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask)
+GL_ENTRY(void, glGetPointerv, GLenum pname, void **params)
+GL_ENTRY(void, glGetPointervKHR, GLenum pname, void **params)
+GL_ENTRY(void, glGetProgramBinary, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glGetProgramBinaryOES, GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+GL_ENTRY(void, glGetProgramInfoLog, GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetProgramInterfaceiv, GLuint program, GLenum programInterface, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetProgramPipelineInfoLog, GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetProgramPipelineInfoLogEXT, GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetProgramPipelineiv, GLuint pipeline, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetProgramPipelineivEXT, GLuint pipeline, GLenum pname, GLint *params)
+GL_ENTRY(GLuint, glGetProgramResourceIndex, GLuint program, GLenum programInterface, const GLchar *name)
+GL_ENTRY(GLint, glGetProgramResourceLocation, GLuint program, GLenum programInterface, const GLchar *name)
+GL_ENTRY(GLint, glGetProgramResourceLocationIndexEXT, GLuint program, GLenum programInterface, const GLchar *name)
+GL_ENTRY(void, glGetProgramResourceName, GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name)
+GL_ENTRY(void, glGetProgramResourcefvNV, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params)
+GL_ENTRY(void, glGetProgramResourceiv, GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params)
+GL_ENTRY(void, glGetProgramiv, GLuint program, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetQueryObjecti64vEXT, GLuint id, GLenum pname, GLint64 *params)
+GL_ENTRY(void, glGetQueryObjectivEXT, GLuint id, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetQueryObjectui64vEXT, GLuint id, GLenum pname, GLuint64 *params)
+GL_ENTRY(void, glGetQueryObjectuiv, GLuint id, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetQueryObjectuivEXT, GLuint id, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetQueryiv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetQueryivEXT, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetRenderbufferParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetRenderbufferParameterivOES, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIiv, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIivEXT, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIivOES, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetSamplerParameterIuiv, GLuint sampler, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetSamplerParameterIuivEXT, GLuint sampler, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetSamplerParameterIuivOES, GLuint sampler, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetSamplerParameterfv, GLuint sampler, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetSamplerParameteriv, GLuint sampler, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetShaderInfoLog, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
+GL_ENTRY(void, glGetShaderPrecisionFormat, GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision)
+GL_ENTRY(void, glGetShaderSource, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source)
+GL_ENTRY(void, glGetShaderiv, GLuint shader, GLenum pname, GLint *params)
 GL_ENTRY(const GLubyte *, glGetString, GLenum name)
 GL_ENTRY(const GLubyte *, glGetStringi, GLenum name, GLuint index)
-GL_ENTRY(void, glGetSynciv, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values)
-GL_ENTRY(void, glGetSyncivAPPLE, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values)
-GL_ENTRY(void, glGetTexEnvfv, GLenum target, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetTexEnviv, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetTexEnvxv, GLenum target, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetTexEnvxvOES, GLenum target, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetTexParameterIivEXT, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetTexParameterIuivEXT, GLenum target, GLenum pname, GLuint * params)
-GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed * params)
-GL_ENTRY(void, glGetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name)
-GL_ENTRY(void, glGetTranslatedShaderSourceANGLE, GLuint shader, GLsizei bufsize, GLsizei * length, GLchar * source)
-GL_ENTRY(GLuint, glGetUniformBlockIndex, GLuint program, const GLchar * uniformBlockName)
-GL_ENTRY(void, glGetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices)
-GL_ENTRY(GLint, glGetUniformLocation, GLuint program, const GLchar * name)
-GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat * params)
-GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint * params)
-GL_ENTRY(void, glGetUniformuiv, GLuint program, GLint location, GLuint * params)
-GL_ENTRY(void, glGetVertexAttribIiv, GLuint index, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetVertexAttribIuiv, GLuint index, GLenum pname, GLuint * params)
-GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void ** pointer)
-GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat * params)
-GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint * params)
-GL_ENTRY(void, glGetnUniformfvEXT, GLuint program, GLint location, GLsizei bufSize, GLfloat * params)
-GL_ENTRY(void, glGetnUniformivEXT, GLuint program, GLint location, GLsizei bufSize, GLint * params)
+GL_ENTRY(void, glGetSynciv, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+GL_ENTRY(void, glGetSyncivAPPLE, GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+GL_ENTRY(void, glGetTexEnvfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexEnviv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexEnvxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexEnvxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexGenfvOES, GLenum coord, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexGenivOES, GLenum coord, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexGenxvOES, GLenum coord, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexLevelParameterfv, GLenum target, GLint level, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexLevelParameteriv, GLenum target, GLint level, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIiv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIivEXT, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIivOES, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterIuiv, GLenum target, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetTexParameterIuivEXT, GLenum target, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetTexParameterIuivOES, GLenum target, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetTexParameterfv, GLenum target, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetTexParameteriv, GLenum target, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetTexParameterxv, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(void, glGetTexParameterxvOES, GLenum target, GLenum pname, GLfixed *params)
+GL_ENTRY(GLuint64, glGetTextureHandleNV, GLuint texture)
+GL_ENTRY(GLuint64, glGetTextureSamplerHandleNV, GLuint texture, GLuint sampler)
+GL_ENTRY(void, glGetTransformFeedbackVarying, GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name)
+GL_ENTRY(void, glGetTranslatedShaderSourceANGLE, GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
+GL_ENTRY(GLuint, glGetUniformBlockIndex, GLuint program, const GLchar *uniformBlockName)
+GL_ENTRY(void, glGetUniformIndices, GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices)
+GL_ENTRY(GLint, glGetUniformLocation, GLuint program, const GLchar *name)
+GL_ENTRY(void, glGetUniformfv, GLuint program, GLint location, GLfloat *params)
+GL_ENTRY(void, glGetUniformiv, GLuint program, GLint location, GLint *params)
+GL_ENTRY(void, glGetUniformuiv, GLuint program, GLint location, GLuint *params)
+GL_ENTRY(void, glGetVertexAttribIiv, GLuint index, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetVertexAttribIuiv, GLuint index, GLenum pname, GLuint *params)
+GL_ENTRY(void, glGetVertexAttribPointerv, GLuint index, GLenum pname, void **pointer)
+GL_ENTRY(void, glGetVertexAttribfv, GLuint index, GLenum pname, GLfloat *params)
+GL_ENTRY(void, glGetVertexAttribiv, GLuint index, GLenum pname, GLint *params)
+GL_ENTRY(void, glGetnUniformfv, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformfvEXT, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformfvKHR, GLuint program, GLint location, GLsizei bufSize, GLfloat *params)
+GL_ENTRY(void, glGetnUniformiv, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetnUniformivEXT, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetnUniformivKHR, GLuint program, GLint location, GLsizei bufSize, GLint *params)
+GL_ENTRY(void, glGetnUniformuiv, GLuint program, GLint location, GLsizei bufSize, GLuint *params)
+GL_ENTRY(void, glGetnUniformuivKHR, GLuint program, GLint location, GLsizei bufSize, GLuint *params)
 GL_ENTRY(void, glHint, GLenum target, GLenum mode)
-GL_ENTRY(void, glInsertEventMarkerEXT, GLsizei length, const GLchar * marker)
-GL_ENTRY(void, glInvalidateFramebuffer, GLenum target, GLsizei numAttachments, const GLenum * attachments)
-GL_ENTRY(void, glInvalidateSubFramebuffer, GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glInsertEventMarkerEXT, GLsizei length, const GLchar *marker)
+GL_ENTRY(void, glInterpolatePathsNV, GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight)
+GL_ENTRY(void, glInvalidateFramebuffer, GLenum target, GLsizei numAttachments, const GLenum *attachments)
+GL_ENTRY(void, glInvalidateSubFramebuffer, GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
 GL_ENTRY(GLboolean, glIsBuffer, GLuint buffer)
 GL_ENTRY(GLboolean, glIsEnabled, GLenum cap)
+GL_ENTRY(GLboolean, glIsEnabledi, GLenum target, GLuint index)
 GL_ENTRY(GLboolean, glIsEnablediEXT, GLenum target, GLuint index)
+GL_ENTRY(GLboolean, glIsEnablediNV, GLenum target, GLuint index)
+GL_ENTRY(GLboolean, glIsEnablediOES, GLenum target, GLuint index)
 GL_ENTRY(GLboolean, glIsFenceNV, GLuint fence)
 GL_ENTRY(GLboolean, glIsFramebuffer, GLuint framebuffer)
 GL_ENTRY(GLboolean, glIsFramebufferOES, GLuint framebuffer)
+GL_ENTRY(GLboolean, glIsImageHandleResidentNV, GLuint64 handle)
+GL_ENTRY(GLboolean, glIsPathNV, GLuint path)
+GL_ENTRY(GLboolean, glIsPointInFillPathNV, GLuint path, GLuint mask, GLfloat x, GLfloat y)
+GL_ENTRY(GLboolean, glIsPointInStrokePathNV, GLuint path, GLfloat x, GLfloat y)
 GL_ENTRY(GLboolean, glIsProgram, GLuint program)
 GL_ENTRY(GLboolean, glIsProgramPipeline, GLuint pipeline)
 GL_ENTRY(GLboolean, glIsProgramPipelineEXT, GLuint pipeline)
@@ -385,172 +487,215 @@
 GL_ENTRY(GLboolean, glIsSync, GLsync sync)
 GL_ENTRY(GLboolean, glIsSyncAPPLE, GLsync sync)
 GL_ENTRY(GLboolean, glIsTexture, GLuint texture)
+GL_ENTRY(GLboolean, glIsTextureHandleResidentNV, GLuint64 handle)
 GL_ENTRY(GLboolean, glIsTransformFeedback, GLuint id)
 GL_ENTRY(GLboolean, glIsVertexArray, GLuint array)
 GL_ENTRY(GLboolean, glIsVertexArrayOES, GLuint array)
-GL_ENTRY(void, glLabelObjectEXT, GLenum type, GLuint object, GLsizei length, const GLchar * label)
+GL_ENTRY(void, glLabelObjectEXT, GLenum type, GLuint object, GLsizei length, const GLchar *label)
 GL_ENTRY(void, glLightModelf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glLightModelfv, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glLightModelx, GLenum pname, GLfixed param)
 GL_ENTRY(void, glLightModelxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed * param)
-GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed * param)
+GL_ENTRY(void, glLightModelxv, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glLightModelxvOES, GLenum pname, const GLfixed *param)
 GL_ENTRY(void, glLightf, GLenum light, GLenum pname, GLfloat param)
-GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glLightfv, GLenum light, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glLightx, GLenum light, GLenum pname, GLfixed param)
 GL_ENTRY(void, glLightxOES, GLenum light, GLenum pname, GLfixed param)
-GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed * params)
-GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed * params)
+GL_ENTRY(void, glLightxv, GLenum light, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glLightxvOES, GLenum light, GLenum pname, const GLfixed *params)
 GL_ENTRY(void, glLineWidth, GLfloat width)
 GL_ENTRY(void, glLineWidthx, GLfixed width)
 GL_ENTRY(void, glLineWidthxOES, GLfixed width)
 GL_ENTRY(void, glLinkProgram, GLuint program)
 GL_ENTRY(void, glLoadIdentity, void)
-GL_ENTRY(void, glLoadMatrixf, const GLfloat * m)
-GL_ENTRY(void, glLoadMatrixx, const GLfixed * m)
-GL_ENTRY(void, glLoadMatrixxOES, const GLfixed * m)
+GL_ENTRY(void, glLoadMatrixf, const GLfloat *m)
+GL_ENTRY(void, glLoadMatrixx, const GLfixed *m)
+GL_ENTRY(void, glLoadMatrixxOES, const GLfixed *m)
 GL_ENTRY(void, glLoadPaletteFromModelViewMatrixOES, void)
 GL_ENTRY(void, glLogicOp, GLenum opcode)
+GL_ENTRY(void, glMakeImageHandleNonResidentNV, GLuint64 handle)
+GL_ENTRY(void, glMakeImageHandleResidentNV, GLuint64 handle, GLenum access)
+GL_ENTRY(void, glMakeTextureHandleNonResidentNV, GLuint64 handle)
+GL_ENTRY(void, glMakeTextureHandleResidentNV, GLuint64 handle)
 GL_ENTRY(void *, glMapBufferOES, GLenum target, GLenum access)
 GL_ENTRY(void *, glMapBufferRange, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
 GL_ENTRY(void *, glMapBufferRangeEXT, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
 GL_ENTRY(void, glMaterialf, GLenum face, GLenum pname, GLfloat param)
-GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glMaterialfv, GLenum face, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glMaterialx, GLenum face, GLenum pname, GLfixed param)
 GL_ENTRY(void, glMaterialxOES, GLenum face, GLenum pname, GLfixed param)
-GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed * param)
-GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed * param)
-GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glMaterialxv, GLenum face, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glMaterialxvOES, GLenum face, GLenum pname, const GLfixed *param)
+GL_ENTRY(void, glMatrixIndexPointerOES, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glMatrixLoad3x2fNV, GLenum matrixMode, const GLfloat *m)
+GL_ENTRY(void, glMatrixLoad3x3fNV, GLenum matrixMode, const GLfloat *m)
+GL_ENTRY(void, glMatrixLoadTranspose3x3fNV, GLenum matrixMode, const GLfloat *m)
 GL_ENTRY(void, glMatrixMode, GLenum mode)
+GL_ENTRY(void, glMatrixMult3x2fNV, GLenum matrixMode, const GLfloat *m)
+GL_ENTRY(void, glMatrixMult3x3fNV, GLenum matrixMode, const GLfloat *m)
+GL_ENTRY(void, glMatrixMultTranspose3x3fNV, GLenum matrixMode, const GLfloat *m)
 GL_ENTRY(void, glMemoryBarrier, GLbitfield barriers)
 GL_ENTRY(void, glMemoryBarrierByRegion, GLbitfield barriers)
+GL_ENTRY(void, glMinSampleShading, GLfloat value)
 GL_ENTRY(void, glMinSampleShadingOES, GLfloat value)
-GL_ENTRY(void, glMultMatrixf, const GLfloat * m)
-GL_ENTRY(void, glMultMatrixx, const GLfixed * m)
-GL_ENTRY(void, glMultMatrixxOES, const GLfixed * m)
-GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount)
-GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount)
-GL_ENTRY(void, glMultiTexCoord1bOES, GLenum texture, GLbyte s)
-GL_ENTRY(void, glMultiTexCoord1bvOES, GLenum texture, const GLbyte * coords)
-GL_ENTRY(void, glMultiTexCoord2bOES, GLenum texture, GLbyte s, GLbyte t)
-GL_ENTRY(void, glMultiTexCoord2bvOES, GLenum texture, const GLbyte * coords)
-GL_ENTRY(void, glMultiTexCoord3bOES, GLenum texture, GLbyte s, GLbyte t, GLbyte r)
-GL_ENTRY(void, glMultiTexCoord3bvOES, GLenum texture, const GLbyte * coords)
-GL_ENTRY(void, glMultiTexCoord4bOES, GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q)
-GL_ENTRY(void, glMultiTexCoord4bvOES, GLenum texture, const GLbyte * coords)
+GL_ENTRY(void, glMultMatrixf, const GLfloat *m)
+GL_ENTRY(void, glMultMatrixx, const GLfixed *m)
+GL_ENTRY(void, glMultMatrixxOES, const GLfixed *m)
+GL_ENTRY(void, glMultiDrawArraysEXT, GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawArraysIndirectEXT, GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride)
+GL_ENTRY(void, glMultiDrawElementsBaseVertexEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex)
+GL_ENTRY(void, glMultiDrawElementsBaseVertexOES, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex)
+GL_ENTRY(void, glMultiDrawElementsEXT, GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount)
+GL_ENTRY(void, glMultiDrawElementsIndirectEXT, GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride)
 GL_ENTRY(void, glMultiTexCoord4f, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
 GL_ENTRY(void, glMultiTexCoord4x, GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
 GL_ENTRY(void, glMultiTexCoord4xOES, GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+GL_ENTRY(void, glNamedFramebufferSampleLocationsfvNV, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v)
 GL_ENTRY(void, glNormal3f, GLfloat nx, GLfloat ny, GLfloat nz)
 GL_ENTRY(void, glNormal3x, GLfixed nx, GLfixed ny, GLfixed nz)
 GL_ENTRY(void, glNormal3xOES, GLfixed nx, GLfixed ny, GLfixed nz)
-GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const void * pointer)
-GL_ENTRY(void, glObjectLabelKHR, GLenum identifier, GLuint name, GLsizei length, const GLchar * label)
-GL_ENTRY(void, glObjectPtrLabelKHR, const void * ptr, GLsizei length, const GLchar * label)
+GL_ENTRY(void, glNormalPointer, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glObjectLabel, GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glObjectLabelKHR, GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glObjectPtrLabel, const void *ptr, GLsizei length, const GLchar *label)
+GL_ENTRY(void, glObjectPtrLabelKHR, const void *ptr, GLsizei length, const GLchar *label)
 GL_ENTRY(void, glOrthof, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
 GL_ENTRY(void, glOrthofOES, GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
 GL_ENTRY(void, glOrthox, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
 GL_ENTRY(void, glOrthoxOES, GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+GL_ENTRY(void, glPatchParameteri, GLenum pname, GLint value)
 GL_ENTRY(void, glPatchParameteriEXT, GLenum pname, GLint value)
+GL_ENTRY(void, glPatchParameteriOES, GLenum pname, GLint value)
+GL_ENTRY(void, glPathCommandsNV, GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords)
+GL_ENTRY(void, glPathCoordsNV, GLuint path, GLsizei numCoords, GLenum coordType, const void *coords)
+GL_ENTRY(void, glPathCoverDepthFuncNV, GLenum func)
+GL_ENTRY(void, glPathDashArrayNV, GLuint path, GLsizei dashCount, const GLfloat *dashArray)
+GL_ENTRY(GLenum, glPathGlyphIndexArrayNV, GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale)
+GL_ENTRY(GLenum, glPathGlyphIndexRangeNV, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2])
+GL_ENTRY(void, glPathGlyphRangeNV, GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale)
+GL_ENTRY(void, glPathGlyphsNV, GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale)
+GL_ENTRY(GLenum, glPathMemoryGlyphIndexArrayNV, GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale)
+GL_ENTRY(void, glPathParameterfNV, GLuint path, GLenum pname, GLfloat value)
+GL_ENTRY(void, glPathParameterfvNV, GLuint path, GLenum pname, const GLfloat *value)
+GL_ENTRY(void, glPathParameteriNV, GLuint path, GLenum pname, GLint value)
+GL_ENTRY(void, glPathParameterivNV, GLuint path, GLenum pname, const GLint *value)
+GL_ENTRY(void, glPathStencilDepthOffsetNV, GLfloat factor, GLfloat units)
+GL_ENTRY(void, glPathStencilFuncNV, GLenum func, GLint ref, GLuint mask)
+GL_ENTRY(void, glPathStringNV, GLuint path, GLenum format, GLsizei length, const void *pathString)
+GL_ENTRY(void, glPathSubCommandsNV, GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords)
+GL_ENTRY(void, glPathSubCoordsNV, GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords)
 GL_ENTRY(void, glPauseTransformFeedback, void)
 GL_ENTRY(void, glPixelStorei, GLenum pname, GLint param)
+GL_ENTRY(GLboolean, glPointAlongPathNV, GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY)
 GL_ENTRY(void, glPointParameterf, GLenum pname, GLfloat param)
-GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glPointParameterfv, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glPointParameterx, GLenum pname, GLfixed param)
 GL_ENTRY(void, glPointParameterxOES, GLenum pname, GLfixed param)
-GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed * params)
-GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed * params)
+GL_ENTRY(void, glPointParameterxv, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glPointParameterxvOES, GLenum pname, const GLfixed *params)
 GL_ENTRY(void, glPointSize, GLfloat size)
-GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glPointSizePointerOES, GLenum type, GLsizei stride, const void *pointer)
 GL_ENTRY(void, glPointSizex, GLfixed size)
 GL_ENTRY(void, glPointSizexOES, GLfixed size)
+GL_ENTRY(void, glPolygonModeNV, GLenum face, GLenum mode)
 GL_ENTRY(void, glPolygonOffset, GLfloat factor, GLfloat units)
 GL_ENTRY(void, glPolygonOffsetx, GLfixed factor, GLfixed units)
 GL_ENTRY(void, glPolygonOffsetxOES, GLfixed factor, GLfixed units)
+GL_ENTRY(void, glPopDebugGroup, void)
 GL_ENTRY(void, glPopDebugGroupKHR, void)
 GL_ENTRY(void, glPopGroupMarkerEXT, void)
 GL_ENTRY(void, glPopMatrix, void)
+GL_ENTRY(void, glPrimitiveBoundingBox, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
 GL_ENTRY(void, glPrimitiveBoundingBoxEXT, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
-GL_ENTRY(void, glProgramBinary, GLuint program, GLenum binaryFormat, const void * binary, GLsizei length)
-GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void * binary, GLint length)
+GL_ENTRY(void, glPrimitiveBoundingBoxOES, GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
+GL_ENTRY(void, glProgramBinary, GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
+GL_ENTRY(void, glProgramBinaryOES, GLuint program, GLenum binaryFormat, const void *binary, GLint length)
 GL_ENTRY(void, glProgramParameteri, GLuint program, GLenum pname, GLint value)
 GL_ENTRY(void, glProgramParameteriEXT, GLuint program, GLenum pname, GLint value)
+GL_ENTRY(void, glProgramPathFragmentInputGenNV, GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs)
 GL_ENTRY(void, glProgramUniform1f, GLuint program, GLint location, GLfloat v0)
 GL_ENTRY(void, glProgramUniform1fEXT, GLuint program, GLint location, GLfloat v0)
-GL_ENTRY(void, glProgramUniform1fv, GLuint program, GLint location, GLsizei count, const GLfloat * value)
-GL_ENTRY(void, glProgramUniform1fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glProgramUniform1fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform1fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glProgramUniform1i, GLuint program, GLint location, GLint v0)
 GL_ENTRY(void, glProgramUniform1iEXT, GLuint program, GLint location, GLint v0)
-GL_ENTRY(void, glProgramUniform1iv, GLuint program, GLint location, GLsizei count, const GLint * value)
-GL_ENTRY(void, glProgramUniform1ivEXT, GLuint program, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glProgramUniform1iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform1ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glProgramUniform1ui, GLuint program, GLint location, GLuint v0)
 GL_ENTRY(void, glProgramUniform1uiEXT, GLuint program, GLint location, GLuint v0)
-GL_ENTRY(void, glProgramUniform1uiv, GLuint program, GLint location, GLsizei count, const GLuint * value)
-GL_ENTRY(void, glProgramUniform1uivEXT, GLuint program, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glProgramUniform1uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform1uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glProgramUniform2f, GLuint program, GLint location, GLfloat v0, GLfloat v1)
 GL_ENTRY(void, glProgramUniform2fEXT, GLuint program, GLint location, GLfloat v0, GLfloat v1)
-GL_ENTRY(void, glProgramUniform2fv, GLuint program, GLint location, GLsizei count, const GLfloat * value)
-GL_ENTRY(void, glProgramUniform2fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glProgramUniform2fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform2fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glProgramUniform2i, GLuint program, GLint location, GLint v0, GLint v1)
 GL_ENTRY(void, glProgramUniform2iEXT, GLuint program, GLint location, GLint v0, GLint v1)
-GL_ENTRY(void, glProgramUniform2iv, GLuint program, GLint location, GLsizei count, const GLint * value)
-GL_ENTRY(void, glProgramUniform2ivEXT, GLuint program, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glProgramUniform2iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform2ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glProgramUniform2ui, GLuint program, GLint location, GLuint v0, GLuint v1)
 GL_ENTRY(void, glProgramUniform2uiEXT, GLuint program, GLint location, GLuint v0, GLuint v1)
-GL_ENTRY(void, glProgramUniform2uiv, GLuint program, GLint location, GLsizei count, const GLuint * value)
-GL_ENTRY(void, glProgramUniform2uivEXT, GLuint program, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glProgramUniform2uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform2uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glProgramUniform3f, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
 GL_ENTRY(void, glProgramUniform3fEXT, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
-GL_ENTRY(void, glProgramUniform3fv, GLuint program, GLint location, GLsizei count, const GLfloat * value)
-GL_ENTRY(void, glProgramUniform3fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glProgramUniform3fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform3fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glProgramUniform3i, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
 GL_ENTRY(void, glProgramUniform3iEXT, GLuint program, GLint location, GLint v0, GLint v1, GLint v2)
-GL_ENTRY(void, glProgramUniform3iv, GLuint program, GLint location, GLsizei count, const GLint * value)
-GL_ENTRY(void, glProgramUniform3ivEXT, GLuint program, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glProgramUniform3iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform3ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glProgramUniform3ui, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
 GL_ENTRY(void, glProgramUniform3uiEXT, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2)
-GL_ENTRY(void, glProgramUniform3uiv, GLuint program, GLint location, GLsizei count, const GLuint * value)
-GL_ENTRY(void, glProgramUniform3uivEXT, GLuint program, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glProgramUniform3uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform3uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glProgramUniform4f, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
 GL_ENTRY(void, glProgramUniform4fEXT, GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
-GL_ENTRY(void, glProgramUniform4fv, GLuint program, GLint location, GLsizei count, const GLfloat * value)
-GL_ENTRY(void, glProgramUniform4fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glProgramUniform4fv, GLuint program, GLint location, GLsizei count, const GLfloat *value)
+GL_ENTRY(void, glProgramUniform4fvEXT, GLuint program, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glProgramUniform4i, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
 GL_ENTRY(void, glProgramUniform4iEXT, GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
-GL_ENTRY(void, glProgramUniform4iv, GLuint program, GLint location, GLsizei count, const GLint * value)
-GL_ENTRY(void, glProgramUniform4ivEXT, GLuint program, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glProgramUniform4iv, GLuint program, GLint location, GLsizei count, const GLint *value)
+GL_ENTRY(void, glProgramUniform4ivEXT, GLuint program, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glProgramUniform4ui, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
 GL_ENTRY(void, glProgramUniform4uiEXT, GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
-GL_ENTRY(void, glProgramUniform4uiv, GLuint program, GLint location, GLsizei count, const GLuint * value)
-GL_ENTRY(void, glProgramUniform4uivEXT, GLuint program, GLint location, GLsizei count, const GLuint * value)
-GL_ENTRY(void, glProgramUniformMatrix2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix2x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix2x3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix2x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix2x4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix3x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix3x2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix3x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix3x4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix4x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix4x2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix4x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glProgramUniformMatrix4x3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glPushDebugGroupKHR, GLenum source, GLuint id, GLsizei length, const GLchar * message)
-GL_ENTRY(void, glPushGroupMarkerEXT, GLsizei length, const GLchar * marker)
+GL_ENTRY(void, glProgramUniform4uiv, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniform4uivEXT, GLuint program, GLint location, GLsizei count, const GLuint *value)
+GL_ENTRY(void, glProgramUniformHandleui64NV, GLuint program, GLint location, GLuint64 value)
+GL_ENTRY(void, glProgramUniformHandleui64vNV, GLuint program, GLint location, GLsizei count, const GLuint64 *values)
+GL_ENTRY(void, glProgramUniformMatrix2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix2x4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix3x4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x2fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x2fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x3fv, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glProgramUniformMatrix4x3fvEXT, GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glPushDebugGroup, GLenum source, GLuint id, GLsizei length, const GLchar *message)
+GL_ENTRY(void, glPushDebugGroupKHR, GLenum source, GLuint id, GLsizei length, const GLchar *message)
+GL_ENTRY(void, glPushGroupMarkerEXT, GLsizei length, const GLchar *marker)
 GL_ENTRY(void, glPushMatrix, void)
 GL_ENTRY(void, glQueryCounterEXT, GLuint id, GLenum target)
-GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed * mantissa, GLint * exponent)
-GL_ENTRY(void, glReadBuffer, GLenum mode)
+GL_ENTRY(GLbitfield, glQueryMatrixxOES, GLfixed *mantissa, GLint *exponent)
+GL_ENTRY(void, glRasterSamplesEXT, GLuint samples, GLboolean fixedsamplelocations)
+GL_ENTRY(void, glReadBuffer, GLenum src)
 GL_ENTRY(void, glReadBufferIndexedEXT, GLenum src, GLint index)
 GL_ENTRY(void, glReadBufferNV, GLenum mode)
-GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels)
-GL_ENTRY(void, glReadnPixelsEXT, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data)
+GL_ENTRY(void, glReadPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels)
+GL_ENTRY(void, glReadnPixels, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+GL_ENTRY(void, glReadnPixelsEXT, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+GL_ENTRY(void, glReadnPixelsKHR, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
 GL_ENTRY(void, glReleaseShaderCompiler, void)
 GL_ENTRY(void, glRenderbufferStorage, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
 GL_ENTRY(void, glRenderbufferStorageMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
@@ -560,135 +705,157 @@
 GL_ENTRY(void, glRenderbufferStorageMultisampleIMG, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 GL_ENTRY(void, glRenderbufferStorageMultisampleNV, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
 GL_ENTRY(void, glRenderbufferStorageOES, GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+GL_ENTRY(void, glResolveDepthValuesNV, void)
 GL_ENTRY(void, glResolveMultisampleFramebufferAPPLE, void)
 GL_ENTRY(void, glResumeTransformFeedback, void)
 GL_ENTRY(void, glRotatef, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
 GL_ENTRY(void, glRotatex, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
 GL_ENTRY(void, glRotatexOES, GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
 GL_ENTRY(void, glSampleCoverage, GLfloat value, GLboolean invert)
-GL_ENTRY(void, glSampleCoverageOES, GLfixed value, GLboolean invert)
 GL_ENTRY(void, glSampleCoveragex, GLclampx value, GLboolean invert)
 GL_ENTRY(void, glSampleCoveragexOES, GLclampx value, GLboolean invert)
 GL_ENTRY(void, glSampleMaski, GLuint maskNumber, GLbitfield mask)
-GL_ENTRY(void, glSamplerParameterIivEXT, GLuint sampler, GLenum pname, const GLint * param)
-GL_ENTRY(void, glSamplerParameterIuivEXT, GLuint sampler, GLenum pname, const GLuint * param)
+GL_ENTRY(void, glSamplerParameterIiv, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterIivEXT, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterIivOES, GLuint sampler, GLenum pname, const GLint *param)
+GL_ENTRY(void, glSamplerParameterIuiv, GLuint sampler, GLenum pname, const GLuint *param)
+GL_ENTRY(void, glSamplerParameterIuivEXT, GLuint sampler, GLenum pname, const GLuint *param)
+GL_ENTRY(void, glSamplerParameterIuivOES, GLuint sampler, GLenum pname, const GLuint *param)
 GL_ENTRY(void, glSamplerParameterf, GLuint sampler, GLenum pname, GLfloat param)
-GL_ENTRY(void, glSamplerParameterfv, GLuint sampler, GLenum pname, const GLfloat * param)
+GL_ENTRY(void, glSamplerParameterfv, GLuint sampler, GLenum pname, const GLfloat *param)
 GL_ENTRY(void, glSamplerParameteri, GLuint sampler, GLenum pname, GLint param)
-GL_ENTRY(void, glSamplerParameteriv, GLuint sampler, GLenum pname, const GLint * param)
+GL_ENTRY(void, glSamplerParameteriv, GLuint sampler, GLenum pname, const GLint *param)
 GL_ENTRY(void, glScalef, GLfloat x, GLfloat y, GLfloat z)
 GL_ENTRY(void, glScalex, GLfixed x, GLfixed y, GLfixed z)
 GL_ENTRY(void, glScalexOES, GLfixed x, GLfixed y, GLfixed z)
 GL_ENTRY(void, glScissor, GLint x, GLint y, GLsizei width, GLsizei height)
-GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint * counterList)
+GL_ENTRY(void, glScissorArrayvNV, GLuint first, GLsizei count, const GLint *v)
+GL_ENTRY(void, glScissorIndexedNV, GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height)
+GL_ENTRY(void, glScissorIndexedvNV, GLuint index, const GLint *v)
+GL_ENTRY(void, glSelectPerfMonitorCountersAMD, GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList)
 GL_ENTRY(void, glSetFenceNV, GLuint fence, GLenum condition)
 GL_ENTRY(void, glShadeModel, GLenum mode)
-GL_ENTRY(void, glShaderBinary, GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length)
-GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length)
+GL_ENTRY(void, glShaderBinary, GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length)
+GL_ENTRY(void, glShaderSource, GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length)
 GL_ENTRY(void, glStartTilingQCOM, GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask)
+GL_ENTRY(void, glStencilFillPathInstancedNV, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues)
+GL_ENTRY(void, glStencilFillPathNV, GLuint path, GLenum fillMode, GLuint mask)
 GL_ENTRY(void, glStencilFunc, GLenum func, GLint ref, GLuint mask)
 GL_ENTRY(void, glStencilFuncSeparate, GLenum face, GLenum func, GLint ref, GLuint mask)
 GL_ENTRY(void, glStencilMask, GLuint mask)
 GL_ENTRY(void, glStencilMaskSeparate, GLenum face, GLuint mask)
 GL_ENTRY(void, glStencilOp, GLenum fail, GLenum zfail, GLenum zpass)
 GL_ENTRY(void, glStencilOpSeparate, GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
+GL_ENTRY(void, glStencilStrokePathInstancedNV, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues)
+GL_ENTRY(void, glStencilStrokePathNV, GLuint path, GLint reference, GLuint mask)
+GL_ENTRY(void, glStencilThenCoverFillPathInstancedNV, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues)
+GL_ENTRY(void, glStencilThenCoverFillPathNV, GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode)
+GL_ENTRY(void, glStencilThenCoverStrokePathInstancedNV, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues)
+GL_ENTRY(void, glStencilThenCoverStrokePathNV, GLuint path, GLint reference, GLuint mask, GLenum coverMode)
+GL_ENTRY(void, glSubpixelPrecisionBiasNV, GLuint xbits, GLuint ybits)
 GL_ENTRY(GLboolean, glTestFenceNV, GLuint fence)
+GL_ENTRY(void, glTexBuffer, GLenum target, GLenum internalformat, GLuint buffer)
 GL_ENTRY(void, glTexBufferEXT, GLenum target, GLenum internalformat, GLuint buffer)
+GL_ENTRY(void, glTexBufferOES, GLenum target, GLenum internalformat, GLuint buffer)
+GL_ENTRY(void, glTexBufferRange, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
 GL_ENTRY(void, glTexBufferRangeEXT, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
-GL_ENTRY(void, glTexCoord1bOES, GLbyte s)
-GL_ENTRY(void, glTexCoord1bvOES, const GLbyte * coords)
-GL_ENTRY(void, glTexCoord2bOES, GLbyte s, GLbyte t)
-GL_ENTRY(void, glTexCoord2bvOES, const GLbyte * coords)
-GL_ENTRY(void, glTexCoord3bOES, GLbyte s, GLbyte t, GLbyte r)
-GL_ENTRY(void, glTexCoord3bvOES, const GLbyte * coords)
-GL_ENTRY(void, glTexCoord4bOES, GLbyte s, GLbyte t, GLbyte r, GLbyte q)
-GL_ENTRY(void, glTexCoord4bvOES, const GLbyte * coords)
-GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glTexBufferRangeOES, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
+GL_ENTRY(void, glTexCoordPointer, GLint size, GLenum type, GLsizei stride, const void *pointer)
 GL_ENTRY(void, glTexEnvf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glTexEnvfv, GLenum target, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glTexEnvi, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint * params)
+GL_ENTRY(void, glTexEnviv, GLenum target, GLenum pname, const GLint *params)
 GL_ENTRY(void, glTexEnvx, GLenum target, GLenum pname, GLfixed param)
 GL_ENTRY(void, glTexEnvxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed * params)
-GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed * params)
+GL_ENTRY(void, glTexEnvxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexEnvxvOES, GLenum target, GLenum pname, const GLfixed *params)
 GL_ENTRY(void, glTexGenfOES, GLenum coord, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glTexGenfvOES, GLenum coord, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glTexGeniOES, GLenum coord, GLenum pname, GLint param)
-GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint * params)
+GL_ENTRY(void, glTexGenivOES, GLenum coord, GLenum pname, const GLint *params)
 GL_ENTRY(void, glTexGenxOES, GLenum coord, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed * params)
-GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels)
-GL_ENTRY(void, glTexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels)
-GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels)
-GL_ENTRY(void, glTexParameterIivEXT, GLenum target, GLenum pname, const GLint * params)
-GL_ENTRY(void, glTexParameterIuivEXT, GLenum target, GLenum pname, const GLuint * params)
+GL_ENTRY(void, glTexGenxvOES, GLenum coord, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexImage2D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexImage3D, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexImage3DOES, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexPageCommitmentEXT, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit)
+GL_ENTRY(void, glTexParameterIiv, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterIivEXT, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterIivOES, GLenum target, GLenum pname, const GLint *params)
+GL_ENTRY(void, glTexParameterIuiv, GLenum target, GLenum pname, const GLuint *params)
+GL_ENTRY(void, glTexParameterIuivEXT, GLenum target, GLenum pname, const GLuint *params)
+GL_ENTRY(void, glTexParameterIuivOES, GLenum target, GLenum pname, const GLuint *params)
 GL_ENTRY(void, glTexParameterf, GLenum target, GLenum pname, GLfloat param)
-GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat * params)
+GL_ENTRY(void, glTexParameterfv, GLenum target, GLenum pname, const GLfloat *params)
 GL_ENTRY(void, glTexParameteri, GLenum target, GLenum pname, GLint param)
-GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint * params)
+GL_ENTRY(void, glTexParameteriv, GLenum target, GLenum pname, const GLint *params)
 GL_ENTRY(void, glTexParameterx, GLenum target, GLenum pname, GLfixed param)
 GL_ENTRY(void, glTexParameterxOES, GLenum target, GLenum pname, GLfixed param)
-GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed * params)
-GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed * params)
+GL_ENTRY(void, glTexParameterxv, GLenum target, GLenum pname, const GLfixed *params)
+GL_ENTRY(void, glTexParameterxvOES, GLenum target, GLenum pname, const GLfixed *params)
 GL_ENTRY(void, glTexStorage1DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
 GL_ENTRY(void, glTexStorage2D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 GL_ENTRY(void, glTexStorage2DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 GL_ENTRY(void, glTexStorage2DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations)
 GL_ENTRY(void, glTexStorage3D, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 GL_ENTRY(void, glTexStorage3DEXT, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+GL_ENTRY(void, glTexStorage3DMultisample, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
 GL_ENTRY(void, glTexStorage3DMultisampleOES, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
-GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels)
-GL_ENTRY(void, glTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels)
-GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels)
+GL_ENTRY(void, glTexSubImage2D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexSubImage3D, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)
+GL_ENTRY(void, glTexSubImage3DOES, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels)
 GL_ENTRY(void, glTextureStorage1DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
 GL_ENTRY(void, glTextureStorage2DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
 GL_ENTRY(void, glTextureStorage3DEXT, GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
 GL_ENTRY(void, glTextureViewEXT, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
-GL_ENTRY(void, glTransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode)
+GL_ENTRY(void, glTextureViewOES, GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers)
+GL_ENTRY(void, glTransformFeedbackVaryings, GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode)
+GL_ENTRY(void, glTransformPathNV, GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues)
 GL_ENTRY(void, glTranslatef, GLfloat x, GLfloat y, GLfloat z)
 GL_ENTRY(void, glTranslatex, GLfixed x, GLfixed y, GLfixed z)
 GL_ENTRY(void, glTranslatexOES, GLfixed x, GLfixed y, GLfixed z)
 GL_ENTRY(void, glUniform1f, GLint location, GLfloat v0)
-GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glUniform1fv, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glUniform1i, GLint location, GLint v0)
-GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glUniform1iv, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glUniform1ui, GLint location, GLuint v0)
-GL_ENTRY(void, glUniform1uiv, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glUniform1uiv, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glUniform2f, GLint location, GLfloat v0, GLfloat v1)
-GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glUniform2fv, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glUniform2i, GLint location, GLint v0, GLint v1)
-GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glUniform2iv, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glUniform2ui, GLint location, GLuint v0, GLuint v1)
-GL_ENTRY(void, glUniform2uiv, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glUniform2uiv, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glUniform3f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
-GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glUniform3fv, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glUniform3i, GLint location, GLint v0, GLint v1, GLint v2)
-GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glUniform3iv, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glUniform3ui, GLint location, GLuint v0, GLuint v1, GLuint v2)
-GL_ENTRY(void, glUniform3uiv, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glUniform3uiv, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glUniform4f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
-GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat * value)
+GL_ENTRY(void, glUniform4fv, GLint location, GLsizei count, const GLfloat *value)
 GL_ENTRY(void, glUniform4i, GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
-GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint * value)
+GL_ENTRY(void, glUniform4iv, GLint location, GLsizei count, const GLint *value)
 GL_ENTRY(void, glUniform4ui, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
-GL_ENTRY(void, glUniform4uiv, GLint location, GLsizei count, const GLuint * value)
+GL_ENTRY(void, glUniform4uiv, GLint location, GLsizei count, const GLuint *value)
 GL_ENTRY(void, glUniformBlockBinding, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
-GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix2x3fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix2x4fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix3x2fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix3x4fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix4x2fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
-GL_ENTRY(void, glUniformMatrix4x3fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
+GL_ENTRY(void, glUniformHandleui64NV, GLint location, GLuint64 value)
+GL_ENTRY(void, glUniformHandleui64vNV, GLint location, GLsizei count, const GLuint64 *value)
+GL_ENTRY(void, glUniformMatrix2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix2x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix2x3fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix2x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix2x4fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3x2fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3x4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix3x4fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4x2fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4x2fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4x3fv, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
+GL_ENTRY(void, glUniformMatrix4x3fvNV, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
 GL_ENTRY(GLboolean, glUnmapBuffer, GLenum target)
 GL_ENTRY(GLboolean, glUnmapBufferOES, GLenum target)
 GL_ENTRY(void, glUseProgram, GLuint program)
@@ -697,20 +864,14 @@
 GL_ENTRY(void, glValidateProgram, GLuint program)
 GL_ENTRY(void, glValidateProgramPipeline, GLuint pipeline)
 GL_ENTRY(void, glValidateProgramPipelineEXT, GLuint pipeline)
-GL_ENTRY(void, glVertex2bOES, GLbyte x)
-GL_ENTRY(void, glVertex2bvOES, const GLbyte * coords)
-GL_ENTRY(void, glVertex3bOES, GLbyte x, GLbyte y)
-GL_ENTRY(void, glVertex3bvOES, const GLbyte * coords)
-GL_ENTRY(void, glVertex4bOES, GLbyte x, GLbyte y, GLbyte z)
-GL_ENTRY(void, glVertex4bvOES, const GLbyte * coords)
 GL_ENTRY(void, glVertexAttrib1f, GLuint index, GLfloat x)
-GL_ENTRY(void, glVertexAttrib1fv, GLuint index, const GLfloat * v)
+GL_ENTRY(void, glVertexAttrib1fv, GLuint index, const GLfloat *v)
 GL_ENTRY(void, glVertexAttrib2f, GLuint index, GLfloat x, GLfloat y)
-GL_ENTRY(void, glVertexAttrib2fv, GLuint index, const GLfloat * v)
+GL_ENTRY(void, glVertexAttrib2fv, GLuint index, const GLfloat *v)
 GL_ENTRY(void, glVertexAttrib3f, GLuint index, GLfloat x, GLfloat y, GLfloat z)
-GL_ENTRY(void, glVertexAttrib3fv, GLuint index, const GLfloat * v)
+GL_ENTRY(void, glVertexAttrib3fv, GLuint index, const GLfloat *v)
 GL_ENTRY(void, glVertexAttrib4f, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-GL_ENTRY(void, glVertexAttrib4fv, GLuint index, const GLfloat * v)
+GL_ENTRY(void, glVertexAttrib4fv, GLuint index, const GLfloat *v)
 GL_ENTRY(void, glVertexAttribBinding, GLuint attribindex, GLuint bindingindex)
 GL_ENTRY(void, glVertexAttribDivisor, GLuint index, GLuint divisor)
 GL_ENTRY(void, glVertexAttribDivisorANGLE, GLuint index, GLuint divisor)
@@ -718,15 +879,19 @@
 GL_ENTRY(void, glVertexAttribDivisorNV, GLuint index, GLuint divisor)
 GL_ENTRY(void, glVertexAttribFormat, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset)
 GL_ENTRY(void, glVertexAttribI4i, GLuint index, GLint x, GLint y, GLint z, GLint w)
-GL_ENTRY(void, glVertexAttribI4iv, GLuint index, const GLint * v)
+GL_ENTRY(void, glVertexAttribI4iv, GLuint index, const GLint *v)
 GL_ENTRY(void, glVertexAttribI4ui, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
-GL_ENTRY(void, glVertexAttribI4uiv, GLuint index, const GLuint * v)
+GL_ENTRY(void, glVertexAttribI4uiv, GLuint index, const GLuint *v)
 GL_ENTRY(void, glVertexAttribIFormat, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)
-GL_ENTRY(void, glVertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer)
-GL_ENTRY(void, glVertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glVertexAttribIPointer, GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer)
+GL_ENTRY(void, glVertexAttribPointer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer)
 GL_ENTRY(void, glVertexBindingDivisor, GLuint bindingindex, GLuint divisor)
-GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glVertexPointer, GLint size, GLenum type, GLsizei stride, const void *pointer)
 GL_ENTRY(void, glViewport, GLint x, GLint y, GLsizei width, GLsizei height)
+GL_ENTRY(void, glViewportArrayvNV, GLuint first, GLsizei count, const GLfloat *v)
+GL_ENTRY(void, glViewportIndexedfNV, GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h)
+GL_ENTRY(void, glViewportIndexedfvNV, GLuint index, const GLfloat *v)
 GL_ENTRY(void, glWaitSync, GLsync sync, GLbitfield flags, GLuint64 timeout)
 GL_ENTRY(void, glWaitSyncAPPLE, GLsync sync, GLbitfield flags, GLuint64 timeout)
-GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const void * pointer)
+GL_ENTRY(void, glWeightPathsNV, GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights)
+GL_ENTRY(void, glWeightPointerOES, GLint size, GLenum type, GLsizei stride, const void *pointer)
diff --git a/opengl/libs/enums.in b/opengl/libs/enums.in
index f3d216d..e052816 100644
--- a/opengl/libs/enums.in
+++ b/opengl/libs/enums.in
@@ -629,6 +629,22 @@
 GL_ENUM(0x8CED,GL_COLOR_ATTACHMENT13)
 GL_ENUM(0x8CEE,GL_COLOR_ATTACHMENT14)
 GL_ENUM(0x8CEF,GL_COLOR_ATTACHMENT15)
+GL_ENUM(0x8CF0,GL_COLOR_ATTACHMENT16)
+GL_ENUM(0x8CF1,GL_COLOR_ATTACHMENT17)
+GL_ENUM(0x8CF2,GL_COLOR_ATTACHMENT18)
+GL_ENUM(0x8CF3,GL_COLOR_ATTACHMENT19)
+GL_ENUM(0x8CF4,GL_COLOR_ATTACHMENT20)
+GL_ENUM(0x8CF5,GL_COLOR_ATTACHMENT21)
+GL_ENUM(0x8CF6,GL_COLOR_ATTACHMENT22)
+GL_ENUM(0x8CF7,GL_COLOR_ATTACHMENT23)
+GL_ENUM(0x8CF8,GL_COLOR_ATTACHMENT24)
+GL_ENUM(0x8CF9,GL_COLOR_ATTACHMENT25)
+GL_ENUM(0x8CFA,GL_COLOR_ATTACHMENT26)
+GL_ENUM(0x8CFB,GL_COLOR_ATTACHMENT27)
+GL_ENUM(0x8CFC,GL_COLOR_ATTACHMENT28)
+GL_ENUM(0x8CFD,GL_COLOR_ATTACHMENT29)
+GL_ENUM(0x8CFE,GL_COLOR_ATTACHMENT30)
+GL_ENUM(0x8CFF,GL_COLOR_ATTACHMENT31)
 GL_ENUM(0x8D56,GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE)
 GL_ENUM(0x8D57,GL_MAX_SAMPLES)
 GL_ENUM(0x140B,GL_HALF_FLOAT)
@@ -897,6 +913,203 @@
 GL_ENUM(0x82D9,GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)
 GL_ENUM(0x82DA,GL_MAX_VERTEX_ATTRIB_BINDINGS)
 GL_ENUM(0x82E5,GL_MAX_VERTEX_ATTRIB_STRIDE)
+GL_ENUM(0x9381,GL_MULTISAMPLE_LINE_WIDTH_RANGE)
+GL_ENUM(0x9382,GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY)
+GL_ENUM(0x9294,GL_MULTIPLY)
+GL_ENUM(0x9295,GL_SCREEN)
+GL_ENUM(0x9296,GL_OVERLAY)
+GL_ENUM(0x9297,GL_DARKEN)
+GL_ENUM(0x9298,GL_LIGHTEN)
+GL_ENUM(0x9299,GL_COLORDODGE)
+GL_ENUM(0x929A,GL_COLORBURN)
+GL_ENUM(0x929B,GL_HARDLIGHT)
+GL_ENUM(0x929C,GL_SOFTLIGHT)
+GL_ENUM(0x929E,GL_DIFFERENCE)
+GL_ENUM(0x92A0,GL_EXCLUSION)
+GL_ENUM(0x92AD,GL_HSL_HUE)
+GL_ENUM(0x92AE,GL_HSL_SATURATION)
+GL_ENUM(0x92AF,GL_HSL_COLOR)
+GL_ENUM(0x92B0,GL_HSL_LUMINOSITY)
+GL_ENUM(0x8242,GL_DEBUG_OUTPUT_SYNCHRONOUS)
+GL_ENUM(0x8243,GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH)
+GL_ENUM(0x8244,GL_DEBUG_CALLBACK_FUNCTION)
+GL_ENUM(0x8245,GL_DEBUG_CALLBACK_USER_PARAM)
+GL_ENUM(0x8246,GL_DEBUG_SOURCE_API)
+GL_ENUM(0x8247,GL_DEBUG_SOURCE_WINDOW_SYSTEM)
+GL_ENUM(0x8248,GL_DEBUG_SOURCE_SHADER_COMPILER)
+GL_ENUM(0x8249,GL_DEBUG_SOURCE_THIRD_PARTY)
+GL_ENUM(0x824A,GL_DEBUG_SOURCE_APPLICATION)
+GL_ENUM(0x824B,GL_DEBUG_SOURCE_OTHER)
+GL_ENUM(0x824C,GL_DEBUG_TYPE_ERROR)
+GL_ENUM(0x824D,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR)
+GL_ENUM(0x824E,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR)
+GL_ENUM(0x824F,GL_DEBUG_TYPE_PORTABILITY)
+GL_ENUM(0x8250,GL_DEBUG_TYPE_PERFORMANCE)
+GL_ENUM(0x8251,GL_DEBUG_TYPE_OTHER)
+GL_ENUM(0x8268,GL_DEBUG_TYPE_MARKER)
+GL_ENUM(0x8269,GL_DEBUG_TYPE_PUSH_GROUP)
+GL_ENUM(0x826A,GL_DEBUG_TYPE_POP_GROUP)
+GL_ENUM(0x826B,GL_DEBUG_SEVERITY_NOTIFICATION)
+GL_ENUM(0x826C,GL_MAX_DEBUG_GROUP_STACK_DEPTH)
+GL_ENUM(0x826D,GL_DEBUG_GROUP_STACK_DEPTH)
+GL_ENUM(0x82E0,GL_BUFFER)
+GL_ENUM(0x82E1,GL_SHADER)
+GL_ENUM(0x82E2,GL_PROGRAM)
+GL_ENUM(0x82E3,GL_QUERY)
+GL_ENUM(0x82E4,GL_PROGRAM_PIPELINE)
+GL_ENUM(0x82E6,GL_SAMPLER)
+GL_ENUM(0x82E8,GL_MAX_LABEL_LENGTH)
+GL_ENUM(0x9143,GL_MAX_DEBUG_MESSAGE_LENGTH)
+GL_ENUM(0x9144,GL_MAX_DEBUG_LOGGED_MESSAGES)
+GL_ENUM(0x9145,GL_DEBUG_LOGGED_MESSAGES)
+GL_ENUM(0x9146,GL_DEBUG_SEVERITY_HIGH)
+GL_ENUM(0x9147,GL_DEBUG_SEVERITY_MEDIUM)
+GL_ENUM(0x9148,GL_DEBUG_SEVERITY_LOW)
+GL_ENUM(0x92E0,GL_DEBUG_OUTPUT)
+GL_ENUM(0x8DD9,GL_GEOMETRY_SHADER)
+GL_ENUM(0x8916,GL_GEOMETRY_VERTICES_OUT)
+GL_ENUM(0x8917,GL_GEOMETRY_INPUT_TYPE)
+GL_ENUM(0x8918,GL_GEOMETRY_OUTPUT_TYPE)
+GL_ENUM(0x887F,GL_GEOMETRY_SHADER_INVOCATIONS)
+GL_ENUM(0x825E,GL_LAYER_PROVOKING_VERTEX)
+GL_ENUM(0x000A,GL_LINES_ADJACENCY)
+GL_ENUM(0x000B,GL_LINE_STRIP_ADJACENCY)
+GL_ENUM(0x000C,GL_TRIANGLES_ADJACENCY)
+GL_ENUM(0x000D,GL_TRIANGLE_STRIP_ADJACENCY)
+GL_ENUM(0x8DDF,GL_MAX_GEOMETRY_UNIFORM_COMPONENTS)
+GL_ENUM(0x8A2C,GL_MAX_GEOMETRY_UNIFORM_BLOCKS)
+GL_ENUM(0x8A32,GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS)
+GL_ENUM(0x9123,GL_MAX_GEOMETRY_INPUT_COMPONENTS)
+GL_ENUM(0x9124,GL_MAX_GEOMETRY_OUTPUT_COMPONENTS)
+GL_ENUM(0x8DE0,GL_MAX_GEOMETRY_OUTPUT_VERTICES)
+GL_ENUM(0x8DE1,GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS)
+GL_ENUM(0x8E5A,GL_MAX_GEOMETRY_SHADER_INVOCATIONS)
+GL_ENUM(0x8C29,GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS)
+GL_ENUM(0x92CF,GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS)
+GL_ENUM(0x92D5,GL_MAX_GEOMETRY_ATOMIC_COUNTERS)
+GL_ENUM(0x90CD,GL_MAX_GEOMETRY_IMAGE_UNIFORMS)
+GL_ENUM(0x90D7,GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS)
+GL_ENUM(0x8E4D,GL_FIRST_VERTEX_CONVENTION)
+GL_ENUM(0x8E4E,GL_LAST_VERTEX_CONVENTION)
+GL_ENUM(0x8260,GL_UNDEFINED_VERTEX)
+GL_ENUM(0x8C87,GL_PRIMITIVES_GENERATED)
+GL_ENUM(0x9312,GL_FRAMEBUFFER_DEFAULT_LAYERS)
+GL_ENUM(0x9317,GL_MAX_FRAMEBUFFER_LAYERS)
+GL_ENUM(0x8DA8,GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS)
+GL_ENUM(0x8DA7,GL_FRAMEBUFFER_ATTACHMENT_LAYERED)
+GL_ENUM(0x9309,GL_REFERENCED_BY_GEOMETRY_SHADER)
+GL_ENUM(0x92BE,GL_PRIMITIVE_BOUNDING_BOX)
+GL_ENUM(0x821E,GL_CONTEXT_FLAGS)
+GL_ENUM(0x8252,GL_LOSE_CONTEXT_ON_RESET)
+GL_ENUM(0x8253,GL_GUILTY_CONTEXT_RESET)
+GL_ENUM(0x8254,GL_INNOCENT_CONTEXT_RESET)
+GL_ENUM(0x8255,GL_UNKNOWN_CONTEXT_RESET)
+GL_ENUM(0x8256,GL_RESET_NOTIFICATION_STRATEGY)
+GL_ENUM(0x8261,GL_NO_RESET_NOTIFICATION)
+GL_ENUM(0x0507,GL_CONTEXT_LOST)
+GL_ENUM(0x8C36,GL_SAMPLE_SHADING)
+GL_ENUM(0x8C37,GL_MIN_SAMPLE_SHADING_VALUE)
+GL_ENUM(0x8E5B,GL_MIN_FRAGMENT_INTERPOLATION_OFFSET)
+GL_ENUM(0x8E5C,GL_MAX_FRAGMENT_INTERPOLATION_OFFSET)
+GL_ENUM(0x8E5D,GL_FRAGMENT_INTERPOLATION_OFFSET_BITS)
+GL_ENUM(0x000E,GL_PATCHES)
+GL_ENUM(0x8E72,GL_PATCH_VERTICES)
+GL_ENUM(0x8E75,GL_TESS_CONTROL_OUTPUT_VERTICES)
+GL_ENUM(0x8E76,GL_TESS_GEN_MODE)
+GL_ENUM(0x8E77,GL_TESS_GEN_SPACING)
+GL_ENUM(0x8E78,GL_TESS_GEN_VERTEX_ORDER)
+GL_ENUM(0x8E79,GL_TESS_GEN_POINT_MODE)
+GL_ENUM(0x8E7A,GL_ISOLINES)
+GL_ENUM(0x0007,GL_QUADS)
+GL_ENUM(0x8E7B,GL_FRACTIONAL_ODD)
+GL_ENUM(0x8E7C,GL_FRACTIONAL_EVEN)
+GL_ENUM(0x8E7D,GL_MAX_PATCH_VERTICES)
+GL_ENUM(0x8E7E,GL_MAX_TESS_GEN_LEVEL)
+GL_ENUM(0x8E7F,GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS)
+GL_ENUM(0x8E80,GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS)
+GL_ENUM(0x8E81,GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS)
+GL_ENUM(0x8E82,GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS)
+GL_ENUM(0x8E83,GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS)
+GL_ENUM(0x8E84,GL_MAX_TESS_PATCH_COMPONENTS)
+GL_ENUM(0x8E85,GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS)
+GL_ENUM(0x8E86,GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS)
+GL_ENUM(0x8E89,GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS)
+GL_ENUM(0x8E8A,GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS)
+GL_ENUM(0x886C,GL_MAX_TESS_CONTROL_INPUT_COMPONENTS)
+GL_ENUM(0x886D,GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS)
+GL_ENUM(0x8E1E,GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS)
+GL_ENUM(0x8E1F,GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS)
+GL_ENUM(0x92CD,GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS)
+GL_ENUM(0x92CE,GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS)
+GL_ENUM(0x92D3,GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS)
+GL_ENUM(0x92D4,GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS)
+GL_ENUM(0x90CB,GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS)
+GL_ENUM(0x90CC,GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS)
+GL_ENUM(0x90D8,GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS)
+GL_ENUM(0x90D9,GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS)
+GL_ENUM(0x8221,GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED)
+GL_ENUM(0x92E7,GL_IS_PER_PATCH)
+GL_ENUM(0x9307,GL_REFERENCED_BY_TESS_CONTROL_SHADER)
+GL_ENUM(0x9308,GL_REFERENCED_BY_TESS_EVALUATION_SHADER)
+GL_ENUM(0x8E88,GL_TESS_CONTROL_SHADER)
+GL_ENUM(0x8E87,GL_TESS_EVALUATION_SHADER)
+GL_ENUM(0x1004,GL_TEXTURE_BORDER_COLOR)
+GL_ENUM(0x812D,GL_CLAMP_TO_BORDER)
+GL_ENUM(0x8C2A,GL_TEXTURE_BUFFER)
+GL_ENUM(0x8C2B,GL_MAX_TEXTURE_BUFFER_SIZE)
+GL_ENUM(0x8C2C,GL_TEXTURE_BINDING_BUFFER)
+GL_ENUM(0x8C2D,GL_TEXTURE_BUFFER_DATA_STORE_BINDING)
+GL_ENUM(0x919F,GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT)
+GL_ENUM(0x8DC2,GL_SAMPLER_BUFFER)
+GL_ENUM(0x8DD0,GL_INT_SAMPLER_BUFFER)
+GL_ENUM(0x8DD8,GL_UNSIGNED_INT_SAMPLER_BUFFER)
+GL_ENUM(0x9051,GL_IMAGE_BUFFER)
+GL_ENUM(0x905C,GL_INT_IMAGE_BUFFER)
+GL_ENUM(0x9067,GL_UNSIGNED_INT_IMAGE_BUFFER)
+GL_ENUM(0x919D,GL_TEXTURE_BUFFER_OFFSET)
+GL_ENUM(0x919E,GL_TEXTURE_BUFFER_SIZE)
+GL_ENUM(0x93B0,GL_COMPRESSED_RGBA_ASTC_4x4)
+GL_ENUM(0x93B1,GL_COMPRESSED_RGBA_ASTC_5x4)
+GL_ENUM(0x93B2,GL_COMPRESSED_RGBA_ASTC_5x5)
+GL_ENUM(0x93B3,GL_COMPRESSED_RGBA_ASTC_6x5)
+GL_ENUM(0x93B4,GL_COMPRESSED_RGBA_ASTC_6x6)
+GL_ENUM(0x93B5,GL_COMPRESSED_RGBA_ASTC_8x5)
+GL_ENUM(0x93B6,GL_COMPRESSED_RGBA_ASTC_8x6)
+GL_ENUM(0x93B7,GL_COMPRESSED_RGBA_ASTC_8x8)
+GL_ENUM(0x93B8,GL_COMPRESSED_RGBA_ASTC_10x5)
+GL_ENUM(0x93B9,GL_COMPRESSED_RGBA_ASTC_10x6)
+GL_ENUM(0x93BA,GL_COMPRESSED_RGBA_ASTC_10x8)
+GL_ENUM(0x93BB,GL_COMPRESSED_RGBA_ASTC_10x10)
+GL_ENUM(0x93BC,GL_COMPRESSED_RGBA_ASTC_12x10)
+GL_ENUM(0x93BD,GL_COMPRESSED_RGBA_ASTC_12x12)
+GL_ENUM(0x93D0,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4)
+GL_ENUM(0x93D1,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4)
+GL_ENUM(0x93D2,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5)
+GL_ENUM(0x93D3,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5)
+GL_ENUM(0x93D4,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6)
+GL_ENUM(0x93D5,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5)
+GL_ENUM(0x93D6,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6)
+GL_ENUM(0x93D7,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8)
+GL_ENUM(0x93D8,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5)
+GL_ENUM(0x93D9,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6)
+GL_ENUM(0x93DA,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8)
+GL_ENUM(0x93DB,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10)
+GL_ENUM(0x93DC,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10)
+GL_ENUM(0x93DD,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12)
+GL_ENUM(0x9009,GL_TEXTURE_CUBE_MAP_ARRAY)
+GL_ENUM(0x900A,GL_TEXTURE_BINDING_CUBE_MAP_ARRAY)
+GL_ENUM(0x900C,GL_SAMPLER_CUBE_MAP_ARRAY)
+GL_ENUM(0x900D,GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW)
+GL_ENUM(0x900E,GL_INT_SAMPLER_CUBE_MAP_ARRAY)
+GL_ENUM(0x900F,GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY)
+GL_ENUM(0x9054,GL_IMAGE_CUBE_MAP_ARRAY)
+GL_ENUM(0x905F,GL_INT_IMAGE_CUBE_MAP_ARRAY)
+GL_ENUM(0x906A,GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY)
+GL_ENUM(0x9102,GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
+GL_ENUM(0x9105,GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY)
+GL_ENUM(0x910B,GL_SAMPLER_2D_MULTISAMPLE_ARRAY)
+GL_ENUM(0x910C,GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY)
+GL_ENUM(0x910D,GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY)
 GL_ENUM(0x8D65,GL_TEXTURE_EXTERNAL_OES)
 GL_ENUM(0x8D67,GL_TEXTURE_BINDING_EXTERNAL_OES)
 GL_ENUM(0x8D68,GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES)
@@ -963,13 +1176,7 @@
 GL_ENUM(0x8D6C,GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT)
 GL_ENUM(0x8365,GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT)
 GL_ENUM(0x8366,GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)
-GL_ENUM(0x8253,GL_GUILTY_CONTEXT_RESET_EXT)
-GL_ENUM(0x8254,GL_INNOCENT_CONTEXT_RESET_EXT)
-GL_ENUM(0x8255,GL_UNKNOWN_CONTEXT_RESET_EXT)
 GL_ENUM(0x90F3,GL_CONTEXT_ROBUST_ACCESS_EXT)
-GL_ENUM(0x8256,GL_RESET_NOTIFICATION_STRATEGY_EXT)
-GL_ENUM(0x8252,GL_LOSE_CONTEXT_ON_RESET_EXT)
-GL_ENUM(0x8261,GL_NO_RESET_NOTIFICATION_EXT)
 GL_ENUM(0x8C42,GL_SRGB_ALPHA_EXT)
 GL_ENUM(0x83F0,GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
 GL_ENUM(0x83F1,GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
@@ -1014,90 +1221,9 @@
 GL_ENUM(0x8FA0,GL_PERFMON_GLOBAL_MODE_QCOM)
 GL_ENUM(0x8823,GL_WRITEONLY_RENDERING_QCOM)
 GL_ENUM(0x9285,GL_BLEND_ADVANCED_COHERENT_KHR)
-GL_ENUM(0x9294,GL_MULTIPLY_KHR)
-GL_ENUM(0x9295,GL_SCREEN_KHR)
-GL_ENUM(0x9296,GL_OVERLAY_KHR)
-GL_ENUM(0x9297,GL_DARKEN_KHR)
-GL_ENUM(0x9298,GL_LIGHTEN_KHR)
-GL_ENUM(0x9299,GL_COLORDODGE_KHR)
-GL_ENUM(0x929A,GL_COLORBURN_KHR)
-GL_ENUM(0x929B,GL_HARDLIGHT_KHR)
-GL_ENUM(0x929C,GL_SOFTLIGHT_KHR)
-GL_ENUM(0x929E,GL_DIFFERENCE_KHR)
-GL_ENUM(0x92A0,GL_EXCLUSION_KHR)
-GL_ENUM(0x92AD,GL_HSL_HUE_KHR)
-GL_ENUM(0x92AE,GL_HSL_SATURATION_KHR)
-GL_ENUM(0x92AF,GL_HSL_COLOR_KHR)
-GL_ENUM(0x92B0,GL_HSL_LUMINOSITY_KHR)
-GL_ENUM(0x82E6,GL_SAMPLER)
-GL_ENUM(0x8242,GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR)
-GL_ENUM(0x8243,GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR)
-GL_ENUM(0x8244,GL_DEBUG_CALLBACK_FUNCTION_KHR)
-GL_ENUM(0x8245,GL_DEBUG_CALLBACK_USER_PARAM_KHR)
-GL_ENUM(0x8246,GL_DEBUG_SOURCE_API_KHR)
-GL_ENUM(0x8247,GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR)
-GL_ENUM(0x8248,GL_DEBUG_SOURCE_SHADER_COMPILER_KHR)
-GL_ENUM(0x8249,GL_DEBUG_SOURCE_THIRD_PARTY_KHR)
-GL_ENUM(0x824A,GL_DEBUG_SOURCE_APPLICATION_KHR)
-GL_ENUM(0x824B,GL_DEBUG_SOURCE_OTHER_KHR)
-GL_ENUM(0x824C,GL_DEBUG_TYPE_ERROR_KHR)
-GL_ENUM(0x824D,GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR)
-GL_ENUM(0x824E,GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR)
-GL_ENUM(0x824F,GL_DEBUG_TYPE_PORTABILITY_KHR)
-GL_ENUM(0x8250,GL_DEBUG_TYPE_PERFORMANCE_KHR)
-GL_ENUM(0x8251,GL_DEBUG_TYPE_OTHER_KHR)
-GL_ENUM(0x8268,GL_DEBUG_TYPE_MARKER_KHR)
-GL_ENUM(0x8269,GL_DEBUG_TYPE_PUSH_GROUP_KHR)
-GL_ENUM(0x826A,GL_DEBUG_TYPE_POP_GROUP_KHR)
-GL_ENUM(0x826B,GL_DEBUG_SEVERITY_NOTIFICATION_KHR)
-GL_ENUM(0x826C,GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR)
-GL_ENUM(0x826D,GL_DEBUG_GROUP_STACK_DEPTH_KHR)
-GL_ENUM(0x82E0,GL_BUFFER_KHR)
-GL_ENUM(0x82E1,GL_SHADER_KHR)
-GL_ENUM(0x82E2,GL_PROGRAM_KHR)
-GL_ENUM(0x82E3,GL_QUERY_KHR)
-GL_ENUM(0x82E8,GL_MAX_LABEL_LENGTH_KHR)
-GL_ENUM(0x9143,GL_MAX_DEBUG_MESSAGE_LENGTH_KHR)
-GL_ENUM(0x9144,GL_MAX_DEBUG_LOGGED_MESSAGES_KHR)
-GL_ENUM(0x9145,GL_DEBUG_LOGGED_MESSAGES_KHR)
-GL_ENUM(0x9146,GL_DEBUG_SEVERITY_HIGH_KHR)
-GL_ENUM(0x9147,GL_DEBUG_SEVERITY_MEDIUM_KHR)
-GL_ENUM(0x9148,GL_DEBUG_SEVERITY_LOW_KHR)
-GL_ENUM(0x92E0,GL_DEBUG_OUTPUT_KHR)
-GL_ENUM(0x93B0,GL_COMPRESSED_RGBA_ASTC_4x4_KHR)
-GL_ENUM(0x93B1,GL_COMPRESSED_RGBA_ASTC_5x4_KHR)
-GL_ENUM(0x93B2,GL_COMPRESSED_RGBA_ASTC_5x5_KHR)
-GL_ENUM(0x93B3,GL_COMPRESSED_RGBA_ASTC_6x5_KHR)
-GL_ENUM(0x93B4,GL_COMPRESSED_RGBA_ASTC_6x6_KHR)
-GL_ENUM(0x93B5,GL_COMPRESSED_RGBA_ASTC_8x5_KHR)
-GL_ENUM(0x93B6,GL_COMPRESSED_RGBA_ASTC_8x6_KHR)
-GL_ENUM(0x93B7,GL_COMPRESSED_RGBA_ASTC_8x8_KHR)
-GL_ENUM(0x93B8,GL_COMPRESSED_RGBA_ASTC_10x5_KHR)
-GL_ENUM(0x93B9,GL_COMPRESSED_RGBA_ASTC_10x6_KHR)
-GL_ENUM(0x93BA,GL_COMPRESSED_RGBA_ASTC_10x8_KHR)
-GL_ENUM(0x93BB,GL_COMPRESSED_RGBA_ASTC_10x10_KHR)
-GL_ENUM(0x93BC,GL_COMPRESSED_RGBA_ASTC_12x10_KHR)
-GL_ENUM(0x93BD,GL_COMPRESSED_RGBA_ASTC_12x12_KHR)
-GL_ENUM(0x93D0,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)
-GL_ENUM(0x93D1,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR)
-GL_ENUM(0x93D2,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR)
-GL_ENUM(0x93D3,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR)
-GL_ENUM(0x93D4,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR)
-GL_ENUM(0x93D5,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR)
-GL_ENUM(0x93D6,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR)
-GL_ENUM(0x93D7,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR)
-GL_ENUM(0x93D8,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR)
-GL_ENUM(0x93D9,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR)
-GL_ENUM(0x93DA,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR)
-GL_ENUM(0x93DB,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR)
-GL_ENUM(0x93DC,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR)
-GL_ENUM(0x93DD,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR)
+GL_ENUM(0x82FB,GL_CONTEXT_RELEASE_BEHAVIOR_KHR)
+GL_ENUM(0x82FC,GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR)
 GL_ENUM(0x8D66,GL_SAMPLER_EXTERNAL_OES)
-GL_ENUM(0x8C36,GL_SAMPLE_SHADING_OES)
-GL_ENUM(0x8C37,GL_MIN_SAMPLE_SHADING_VALUE_OES)
-GL_ENUM(0x8E5B,GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES)
-GL_ENUM(0x8E5C,GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES)
-GL_ENUM(0x8E5D,GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES)
 GL_ENUM(0x93C0,GL_COMPRESSED_RGBA_ASTC_3x3x3_OES)
 GL_ENUM(0x93C1,GL_COMPRESSED_RGBA_ASTC_4x3x3_OES)
 GL_ENUM(0x93C2,GL_COMPRESSED_RGBA_ASTC_4x4x3_OES)
@@ -1119,11 +1245,10 @@
 GL_ENUM(0x93E8,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES)
 GL_ENUM(0x93E9,GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES)
 GL_ENUM(0x8D61,GL_HALF_FLOAT_OES)
-GL_ENUM(0x9102,GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES)
-GL_ENUM(0x9105,GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES)
-GL_ENUM(0x910B,GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES)
-GL_ENUM(0x910C,GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES)
-GL_ENUM(0x910D,GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES)
+GL_ENUM(0x82DB,GL_TEXTURE_VIEW_MIN_LEVEL_OES)
+GL_ENUM(0x82DC,GL_TEXTURE_VIEW_NUM_LEVELS_OES)
+GL_ENUM(0x82DD,GL_TEXTURE_VIEW_MIN_LAYER_OES)
+GL_ENUM(0x82DE,GL_TEXTURE_VIEW_NUM_LAYERS_OES)
 GL_ENUM(0x8DF6,GL_UNSIGNED_INT_10_10_10_2_OES)
 GL_ENUM(0x8DF7,GL_INT_10_10_10_2_OES)
 GL_ENUM(0x8BC0,GL_COUNTER_TYPE_AMD)
@@ -1141,6 +1266,8 @@
 GL_ENUM(0x93A2,GL_TEXTURE_USAGE_ANGLE)
 GL_ENUM(0x93A3,GL_FRAMEBUFFER_ATTACHMENT_ANGLE)
 GL_ENUM(0x93A0,GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE)
+GL_ENUM(0x3006,GL_CLIP_DISTANCE6_APPLE)
+GL_ENUM(0x3007,GL_CLIP_DISTANCE7_APPLE)
 GL_ENUM(0x8A1F,GL_RGB_422_APPLE)
 GL_ENUM(0x85BA,GL_UNSIGNED_SHORT_8_8_APPLE)
 GL_ENUM(0x85BB,GL_UNSIGNED_SHORT_8_8_REV_APPLE)
@@ -1149,7 +1276,18 @@
 GL_ENUM(0x8F60,GL_MALI_SHADER_BINARY_ARM)
 GL_ENUM(0x8F65,GL_FETCH_PER_SAMPLE_ARM)
 GL_ENUM(0x8F66,GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM)
+GL_ENUM(0x9251,GL_SMAPHS30_PROGRAM_BINARY_DMP)
+GL_ENUM(0x9252,GL_SMAPHS_PROGRAM_BINARY_DMP)
+GL_ENUM(0x9253,GL_DMP_PROGRAM_BINARY_DMP)
 GL_ENUM(0x9250,GL_SHADER_BINARY_DMP)
+GL_ENUM(0x8BE7,GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT)
+GL_ENUM(0x88F9,GL_SRC1_COLOR_EXT)
+GL_ENUM(0x88FA,GL_ONE_MINUS_SRC1_COLOR_EXT)
+GL_ENUM(0x88FB,GL_ONE_MINUS_SRC1_ALPHA_EXT)
+GL_ENUM(0x930F,GL_LOCATION_INDEX_EXT)
+GL_ENUM(0x88FC,GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT)
+GL_ENUM(0x821F,GL_BUFFER_IMMUTABLE_STORAGE_EXT)
+GL_ENUM(0x8220,GL_BUFFER_STORAGE_FLAGS_EXT)
 GL_ENUM(0x8A4F,GL_PROGRAM_PIPELINE_OBJECT_EXT)
 GL_ENUM(0x8B40,GL_PROGRAM_OBJECT_EXT)
 GL_ENUM(0x8B48,GL_SHADER_OBJECT_EXT)
@@ -1160,131 +1298,59 @@
 GL_ENUM(0x88BF,GL_TIME_ELAPSED_EXT)
 GL_ENUM(0x8E28,GL_TIMESTAMP_EXT)
 GL_ENUM(0x8FBB,GL_GPU_DISJOINT_EXT)
-GL_ENUM(0x8DD9,GL_GEOMETRY_SHADER_EXT)
-GL_ENUM(0x8916,GL_GEOMETRY_LINKED_VERTICES_OUT_EXT)
-GL_ENUM(0x8917,GL_GEOMETRY_LINKED_INPUT_TYPE_EXT)
-GL_ENUM(0x8918,GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT)
-GL_ENUM(0x887F,GL_GEOMETRY_SHADER_INVOCATIONS_EXT)
-GL_ENUM(0x825E,GL_LAYER_PROVOKING_VERTEX_EXT)
-GL_ENUM(0x000A,GL_LINES_ADJACENCY_EXT)
-GL_ENUM(0x000B,GL_LINE_STRIP_ADJACENCY_EXT)
-GL_ENUM(0x000C,GL_TRIANGLES_ADJACENCY_EXT)
-GL_ENUM(0x000D,GL_TRIANGLE_STRIP_ADJACENCY_EXT)
-GL_ENUM(0x8DDF,GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT)
-GL_ENUM(0x8A2C,GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT)
-GL_ENUM(0x8A32,GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT)
-GL_ENUM(0x9123,GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT)
-GL_ENUM(0x9124,GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT)
-GL_ENUM(0x8DE0,GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT)
-GL_ENUM(0x8DE1,GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT)
-GL_ENUM(0x8E5A,GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT)
-GL_ENUM(0x8C29,GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT)
-GL_ENUM(0x92CF,GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT)
-GL_ENUM(0x92D5,GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT)
-GL_ENUM(0x90CD,GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT)
-GL_ENUM(0x90D7,GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT)
-GL_ENUM(0x8E4D,GL_FIRST_VERTEX_CONVENTION_EXT)
-GL_ENUM(0x8E4E,GL_LAST_VERTEX_CONVENTION_EXT)
-GL_ENUM(0x8260,GL_UNDEFINED_VERTEX_EXT)
-GL_ENUM(0x8C87,GL_PRIMITIVES_GENERATED_EXT)
-GL_ENUM(0x9312,GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT)
-GL_ENUM(0x9317,GL_MAX_FRAMEBUFFER_LAYERS_EXT)
-GL_ENUM(0x8DA8,GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT)
-GL_ENUM(0x8DA7,GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT)
-GL_ENUM(0x9309,GL_REFERENCED_BY_GEOMETRY_SHADER_EXT)
 GL_ENUM(0x90F0,GL_COLOR_ATTACHMENT_EXT)
 GL_ENUM(0x90F1,GL_MULTIVIEW_EXT)
 GL_ENUM(0x0C01,GL_DRAW_BUFFER_EXT)
 GL_ENUM(0x90F2,GL_MAX_MULTIVIEW_BUFFERS_EXT)
-GL_ENUM(0x92BE,GL_PRIMITIVE_BOUNDING_BOX_EXT)
 GL_ENUM(0x8A54,GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT)
 GL_ENUM(0x8A55,GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT)
 GL_ENUM(0x8A56,GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT)
 GL_ENUM(0x8A57,GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT)
 GL_ENUM(0x93F0,GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG)
 GL_ENUM(0x93F1,GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG)
+GL_ENUM(0x9327,GL_RASTER_MULTISAMPLE_EXT)
+GL_ENUM(0x9328,GL_RASTER_SAMPLES_EXT)
+GL_ENUM(0x9329,GL_MAX_RASTER_SAMPLES_EXT)
+GL_ENUM(0x932A,GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT)
+GL_ENUM(0x932B,GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT)
+GL_ENUM(0x932C,GL_EFFECTIVE_RASTER_SAMPLES_EXT)
+GL_ENUM(0x8F98,GL_R16_SNORM_EXT)
+GL_ENUM(0x8F99,GL_RG16_SNORM_EXT)
+GL_ENUM(0x8F9B,GL_RGBA16_SNORM_EXT)
 GL_ENUM(0x8DB9,GL_FRAMEBUFFER_SRGB_EXT)
 GL_ENUM(0x8A52,GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT)
 GL_ENUM(0x8F63,GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT)
 GL_ENUM(0x8F67,GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT)
 GL_ENUM(0x8F64,GL_SHADER_PIXEL_LOCAL_STORAGE_EXT)
-GL_ENUM(0x000E,GL_PATCHES_EXT)
-GL_ENUM(0x8E72,GL_PATCH_VERTICES_EXT)
-GL_ENUM(0x8E75,GL_TESS_CONTROL_OUTPUT_VERTICES_EXT)
-GL_ENUM(0x8E76,GL_TESS_GEN_MODE_EXT)
-GL_ENUM(0x8E77,GL_TESS_GEN_SPACING_EXT)
-GL_ENUM(0x8E78,GL_TESS_GEN_VERTEX_ORDER_EXT)
-GL_ENUM(0x8E79,GL_TESS_GEN_POINT_MODE_EXT)
-GL_ENUM(0x8E7A,GL_ISOLINES_EXT)
-GL_ENUM(0x0007,GL_QUADS_EXT)
-GL_ENUM(0x8E7B,GL_FRACTIONAL_ODD_EXT)
-GL_ENUM(0x8E7C,GL_FRACTIONAL_EVEN_EXT)
-GL_ENUM(0x8E7D,GL_MAX_PATCH_VERTICES_EXT)
-GL_ENUM(0x8E7E,GL_MAX_TESS_GEN_LEVEL_EXT)
-GL_ENUM(0x8E7F,GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT)
-GL_ENUM(0x8E80,GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT)
-GL_ENUM(0x8E81,GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT)
-GL_ENUM(0x8E82,GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT)
-GL_ENUM(0x8E83,GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT)
-GL_ENUM(0x8E84,GL_MAX_TESS_PATCH_COMPONENTS_EXT)
-GL_ENUM(0x8E85,GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT)
-GL_ENUM(0x8E86,GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT)
-GL_ENUM(0x8E89,GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT)
-GL_ENUM(0x8E8A,GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT)
-GL_ENUM(0x886C,GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT)
-GL_ENUM(0x886D,GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT)
-GL_ENUM(0x8E1E,GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT)
-GL_ENUM(0x8E1F,GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT)
-GL_ENUM(0x92CD,GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT)
-GL_ENUM(0x92CE,GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT)
-GL_ENUM(0x92D3,GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT)
-GL_ENUM(0x92D4,GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT)
-GL_ENUM(0x90CB,GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT)
-GL_ENUM(0x90CC,GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT)
-GL_ENUM(0x90D8,GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT)
-GL_ENUM(0x90D9,GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT)
-GL_ENUM(0x8221,GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED)
-GL_ENUM(0x92E7,GL_IS_PER_PATCH_EXT)
-GL_ENUM(0x9307,GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT)
-GL_ENUM(0x9308,GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT)
-GL_ENUM(0x8E88,GL_TESS_CONTROL_SHADER_EXT)
-GL_ENUM(0x8E87,GL_TESS_EVALUATION_SHADER_EXT)
-GL_ENUM(0x1004,GL_TEXTURE_BORDER_COLOR_EXT)
-GL_ENUM(0x812D,GL_CLAMP_TO_BORDER_EXT)
-GL_ENUM(0x8C2A,GL_TEXTURE_BUFFER_EXT)
-GL_ENUM(0x8C2B,GL_MAX_TEXTURE_BUFFER_SIZE_EXT)
-GL_ENUM(0x8C2C,GL_TEXTURE_BINDING_BUFFER_EXT)
-GL_ENUM(0x8C2D,GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT)
-GL_ENUM(0x919F,GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT)
-GL_ENUM(0x8DC2,GL_SAMPLER_BUFFER_EXT)
-GL_ENUM(0x8DD0,GL_INT_SAMPLER_BUFFER_EXT)
-GL_ENUM(0x8DD8,GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT)
-GL_ENUM(0x9051,GL_IMAGE_BUFFER_EXT)
-GL_ENUM(0x905C,GL_INT_IMAGE_BUFFER_EXT)
-GL_ENUM(0x9067,GL_UNSIGNED_INT_IMAGE_BUFFER_EXT)
-GL_ENUM(0x919D,GL_TEXTURE_BUFFER_OFFSET_EXT)
-GL_ENUM(0x919E,GL_TEXTURE_BUFFER_SIZE_EXT)
-GL_ENUM(0x9009,GL_TEXTURE_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x900A,GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x900C,GL_SAMPLER_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x900D,GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT)
-GL_ENUM(0x900E,GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x900F,GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x9054,GL_IMAGE_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x905F,GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT)
-GL_ENUM(0x906A,GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT)
+GL_ENUM(0x91A6,GL_TEXTURE_SPARSE_EXT)
+GL_ENUM(0x91A7,GL_VIRTUAL_PAGE_SIZE_INDEX_EXT)
+GL_ENUM(0x91AA,GL_NUM_SPARSE_LEVELS_EXT)
+GL_ENUM(0x91A8,GL_NUM_VIRTUAL_PAGE_SIZES_EXT)
+GL_ENUM(0x9195,GL_VIRTUAL_PAGE_SIZE_X_EXT)
+GL_ENUM(0x9196,GL_VIRTUAL_PAGE_SIZE_Y_EXT)
+GL_ENUM(0x9197,GL_VIRTUAL_PAGE_SIZE_Z_EXT)
+GL_ENUM(0x9198,GL_MAX_SPARSE_TEXTURE_SIZE_EXT)
+GL_ENUM(0x9199,GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT)
+GL_ENUM(0x919A,GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT)
+GL_ENUM(0x91A9,GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT)
+GL_ENUM(0x822A,GL_R16_EXT)
+GL_ENUM(0x822C,GL_RG16_EXT)
+GL_ENUM(0x805B,GL_RGBA16_EXT)
+GL_ENUM(0x8054,GL_RGB16_EXT)
+GL_ENUM(0x8F9A,GL_RGB16_SNORM_EXT)
+GL_ENUM(0x8FBD,GL_SR8_EXT)
+GL_ENUM(0x8FBE,GL_SRG8_EXT)
 GL_ENUM(0x8A48,GL_TEXTURE_SRGB_DECODE_EXT)
 GL_ENUM(0x8A49,GL_DECODE_EXT)
 GL_ENUM(0x8A4A,GL_SKIP_DECODE_EXT)
-GL_ENUM(0x82DB,GL_TEXTURE_VIEW_MIN_LEVEL_EXT)
-GL_ENUM(0x82DC,GL_TEXTURE_VIEW_NUM_LEVELS_EXT)
-GL_ENUM(0x82DD,GL_TEXTURE_VIEW_MIN_LAYER_EXT)
-GL_ENUM(0x82DE,GL_TEXTURE_VIEW_NUM_LAYERS_EXT)
 GL_ENUM(0x9260,GL_GCCSO_SHADER_BINARY_FJ)
 GL_ENUM(0x9130,GL_SGX_PROGRAM_BINARY_IMG)
 GL_ENUM(0x8C0A,GL_SGX_BINARY_IMG)
 GL_ENUM(0x9137,GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG)
 GL_ENUM(0x9138,GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG)
+GL_ENUM(0x9139,GL_CUBIC_IMG)
+GL_ENUM(0x913A,GL_CUBIC_MIPMAP_NEAREST_IMG)
+GL_ENUM(0x913B,GL_CUBIC_MIPMAP_LINEAR_IMG)
 GL_ENUM(0x00000000,GL_PERFQUERY_SINGLE_CONTEXT_INTEL)
 GL_ENUM(0x00000001,GL_PERFQUERY_GLOBAL_CONTEXT_INTEL)
 GL_ENUM(0x83FB,GL_PERFQUERY_WAIT_INTEL)
@@ -1335,6 +1401,14 @@
 GL_ENUM(0x9288,GL_SRC_OVER_NV)
 GL_ENUM(0x9282,GL_UNCORRELATED_NV)
 GL_ENUM(0x92A6,GL_VIVIDLIGHT_NV)
+GL_ENUM(0x8E13,GL_QUERY_WAIT_NV)
+GL_ENUM(0x8E14,GL_QUERY_NO_WAIT_NV)
+GL_ENUM(0x8E15,GL_QUERY_BY_REGION_WAIT_NV)
+GL_ENUM(0x8E16,GL_QUERY_BY_REGION_NO_WAIT_NV)
+GL_ENUM(0x9346,GL_CONSERVATIVE_RASTERIZATION_NV)
+GL_ENUM(0x9347,GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV)
+GL_ENUM(0x9348,GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV)
+GL_ENUM(0x9349,GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV)
 GL_ENUM(0x8ED0,GL_COVERAGE_COMPONENT_NV)
 GL_ENUM(0x8ED1,GL_COVERAGE_COMPONENT4_NV)
 GL_ENUM(0x8ED2,GL_COVERAGE_ATTACHMENT_NV)
@@ -1344,6 +1418,148 @@
 GL_ENUM(0x8ED6,GL_COVERAGE_EDGE_FRAGMENTS_NV)
 GL_ENUM(0x8ED7,GL_COVERAGE_AUTOMATIC_NV)
 GL_ENUM(0x8E2C,GL_DEPTH_COMPONENT16_NONLINEAR_NV)
+GL_ENUM(0x933C,GL_FILL_RECTANGLE_NV)
+GL_ENUM(0x92DD,GL_FRAGMENT_COVERAGE_TO_COLOR_NV)
+GL_ENUM(0x92DE,GL_FRAGMENT_COVERAGE_COLOR_NV)
+GL_ENUM(0x9331,GL_COVERAGE_MODULATION_TABLE_NV)
+GL_ENUM(0x8E20,GL_COLOR_SAMPLES_NV)
+GL_ENUM(0x932D,GL_DEPTH_SAMPLES_NV)
+GL_ENUM(0x932E,GL_STENCIL_SAMPLES_NV)
+GL_ENUM(0x932F,GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV)
+GL_ENUM(0x9330,GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV)
+GL_ENUM(0x9332,GL_COVERAGE_MODULATION_NV)
+GL_ENUM(0x9333,GL_COVERAGE_MODULATION_TABLE_SIZE_NV)
+GL_ENUM(0x9371,GL_MULTISAMPLES_NV)
+GL_ENUM(0x9372,GL_SUPERSAMPLE_SCALE_X_NV)
+GL_ENUM(0x9373,GL_SUPERSAMPLE_SCALE_Y_NV)
+GL_ENUM(0x9374,GL_CONFORMANT_NV)
+GL_ENUM(0x9070,GL_PATH_FORMAT_SVG_NV)
+GL_ENUM(0x9071,GL_PATH_FORMAT_PS_NV)
+GL_ENUM(0x9072,GL_STANDARD_FONT_NAME_NV)
+GL_ENUM(0x9073,GL_SYSTEM_FONT_NAME_NV)
+GL_ENUM(0x9074,GL_FILE_NAME_NV)
+GL_ENUM(0x9075,GL_PATH_STROKE_WIDTH_NV)
+GL_ENUM(0x9076,GL_PATH_END_CAPS_NV)
+GL_ENUM(0x9077,GL_PATH_INITIAL_END_CAP_NV)
+GL_ENUM(0x9078,GL_PATH_TERMINAL_END_CAP_NV)
+GL_ENUM(0x9079,GL_PATH_JOIN_STYLE_NV)
+GL_ENUM(0x907A,GL_PATH_MITER_LIMIT_NV)
+GL_ENUM(0x907B,GL_PATH_DASH_CAPS_NV)
+GL_ENUM(0x907C,GL_PATH_INITIAL_DASH_CAP_NV)
+GL_ENUM(0x907D,GL_PATH_TERMINAL_DASH_CAP_NV)
+GL_ENUM(0x907E,GL_PATH_DASH_OFFSET_NV)
+GL_ENUM(0x907F,GL_PATH_CLIENT_LENGTH_NV)
+GL_ENUM(0x9080,GL_PATH_FILL_MODE_NV)
+GL_ENUM(0x9081,GL_PATH_FILL_MASK_NV)
+GL_ENUM(0x9082,GL_PATH_FILL_COVER_MODE_NV)
+GL_ENUM(0x9083,GL_PATH_STROKE_COVER_MODE_NV)
+GL_ENUM(0x9084,GL_PATH_STROKE_MASK_NV)
+GL_ENUM(0x9088,GL_COUNT_UP_NV)
+GL_ENUM(0x9089,GL_COUNT_DOWN_NV)
+GL_ENUM(0x908A,GL_PATH_OBJECT_BOUNDING_BOX_NV)
+GL_ENUM(0x908B,GL_CONVEX_HULL_NV)
+GL_ENUM(0x908D,GL_BOUNDING_BOX_NV)
+GL_ENUM(0x908E,GL_TRANSLATE_X_NV)
+GL_ENUM(0x908F,GL_TRANSLATE_Y_NV)
+GL_ENUM(0x9090,GL_TRANSLATE_2D_NV)
+GL_ENUM(0x9091,GL_TRANSLATE_3D_NV)
+GL_ENUM(0x9092,GL_AFFINE_2D_NV)
+GL_ENUM(0x9094,GL_AFFINE_3D_NV)
+GL_ENUM(0x9096,GL_TRANSPOSE_AFFINE_2D_NV)
+GL_ENUM(0x9098,GL_TRANSPOSE_AFFINE_3D_NV)
+GL_ENUM(0x909A,GL_UTF8_NV)
+GL_ENUM(0x909B,GL_UTF16_NV)
+GL_ENUM(0x909C,GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV)
+GL_ENUM(0x909D,GL_PATH_COMMAND_COUNT_NV)
+GL_ENUM(0x909E,GL_PATH_COORD_COUNT_NV)
+GL_ENUM(0x909F,GL_PATH_DASH_ARRAY_COUNT_NV)
+GL_ENUM(0x90A0,GL_PATH_COMPUTED_LENGTH_NV)
+GL_ENUM(0x90A1,GL_PATH_FILL_BOUNDING_BOX_NV)
+GL_ENUM(0x90A2,GL_PATH_STROKE_BOUNDING_BOX_NV)
+GL_ENUM(0x90A3,GL_SQUARE_NV)
+GL_ENUM(0x90A4,GL_ROUND_NV)
+GL_ENUM(0x90A5,GL_TRIANGULAR_NV)
+GL_ENUM(0x90A6,GL_BEVEL_NV)
+GL_ENUM(0x90A7,GL_MITER_REVERT_NV)
+GL_ENUM(0x90A8,GL_MITER_TRUNCATE_NV)
+GL_ENUM(0x90A9,GL_SKIP_MISSING_GLYPH_NV)
+GL_ENUM(0x90AA,GL_USE_MISSING_GLYPH_NV)
+GL_ENUM(0x90AB,GL_PATH_ERROR_POSITION_NV)
+GL_ENUM(0x90AD,GL_ACCUM_ADJACENT_PAIRS_NV)
+GL_ENUM(0x90AE,GL_ADJACENT_PAIRS_NV)
+GL_ENUM(0x90AF,GL_FIRST_TO_REST_NV)
+GL_ENUM(0x90B0,GL_PATH_GEN_MODE_NV)
+GL_ENUM(0x90B1,GL_PATH_GEN_COEFF_NV)
+GL_ENUM(0x90B3,GL_PATH_GEN_COMPONENTS_NV)
+GL_ENUM(0x90B7,GL_PATH_STENCIL_FUNC_NV)
+GL_ENUM(0x90B8,GL_PATH_STENCIL_REF_NV)
+GL_ENUM(0x90B9,GL_PATH_STENCIL_VALUE_MASK_NV)
+GL_ENUM(0x90BD,GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV)
+GL_ENUM(0x90BE,GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV)
+GL_ENUM(0x90BF,GL_PATH_COVER_DEPTH_FUNC_NV)
+GL_ENUM(0x90B4,GL_PATH_DASH_OFFSET_RESET_NV)
+GL_ENUM(0x90B5,GL_MOVE_TO_RESETS_NV)
+GL_ENUM(0x90B6,GL_MOVE_TO_CONTINUES_NV)
+GL_ENUM(0x00,GL_CLOSE_PATH_NV)
+GL_ENUM(0x02,GL_MOVE_TO_NV)
+GL_ENUM(0x03,GL_RELATIVE_MOVE_TO_NV)
+GL_ENUM(0x04,GL_LINE_TO_NV)
+GL_ENUM(0x05,GL_RELATIVE_LINE_TO_NV)
+GL_ENUM(0x06,GL_HORIZONTAL_LINE_TO_NV)
+GL_ENUM(0x07,GL_RELATIVE_HORIZONTAL_LINE_TO_NV)
+GL_ENUM(0x08,GL_VERTICAL_LINE_TO_NV)
+GL_ENUM(0x09,GL_RELATIVE_VERTICAL_LINE_TO_NV)
+GL_ENUM(0x0A,GL_QUADRATIC_CURVE_TO_NV)
+GL_ENUM(0x0B,GL_RELATIVE_QUADRATIC_CURVE_TO_NV)
+GL_ENUM(0x0C,GL_CUBIC_CURVE_TO_NV)
+GL_ENUM(0x0D,GL_RELATIVE_CUBIC_CURVE_TO_NV)
+GL_ENUM(0x0E,GL_SMOOTH_QUADRATIC_CURVE_TO_NV)
+GL_ENUM(0x0F,GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV)
+GL_ENUM(0x10,GL_SMOOTH_CUBIC_CURVE_TO_NV)
+GL_ENUM(0x11,GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV)
+GL_ENUM(0x12,GL_SMALL_CCW_ARC_TO_NV)
+GL_ENUM(0x13,GL_RELATIVE_SMALL_CCW_ARC_TO_NV)
+GL_ENUM(0x14,GL_SMALL_CW_ARC_TO_NV)
+GL_ENUM(0x15,GL_RELATIVE_SMALL_CW_ARC_TO_NV)
+GL_ENUM(0x16,GL_LARGE_CCW_ARC_TO_NV)
+GL_ENUM(0x17,GL_RELATIVE_LARGE_CCW_ARC_TO_NV)
+GL_ENUM(0x18,GL_LARGE_CW_ARC_TO_NV)
+GL_ENUM(0x19,GL_RELATIVE_LARGE_CW_ARC_TO_NV)
+GL_ENUM(0xF0,GL_RESTART_PATH_NV)
+GL_ENUM(0xF2,GL_DUP_FIRST_CUBIC_CURVE_TO_NV)
+GL_ENUM(0xF4,GL_DUP_LAST_CUBIC_CURVE_TO_NV)
+GL_ENUM(0xF6,GL_RECT_NV)
+GL_ENUM(0xF8,GL_CIRCULAR_CCW_ARC_TO_NV)
+GL_ENUM(0xFA,GL_CIRCULAR_CW_ARC_TO_NV)
+GL_ENUM(0xFC,GL_CIRCULAR_TANGENT_ARC_TO_NV)
+GL_ENUM(0xFE,GL_ARC_TO_NV)
+GL_ENUM(0xFF,GL_RELATIVE_ARC_TO_NV)
+GL_ENUM(0xE8,GL_ROUNDED_RECT_NV)
+GL_ENUM(0xE9,GL_RELATIVE_ROUNDED_RECT_NV)
+GL_ENUM(0xEA,GL_ROUNDED_RECT2_NV)
+GL_ENUM(0xEB,GL_RELATIVE_ROUNDED_RECT2_NV)
+GL_ENUM(0xEC,GL_ROUNDED_RECT4_NV)
+GL_ENUM(0xED,GL_RELATIVE_ROUNDED_RECT4_NV)
+GL_ENUM(0xEE,GL_ROUNDED_RECT8_NV)
+GL_ENUM(0xEF,GL_RELATIVE_ROUNDED_RECT8_NV)
+GL_ENUM(0xF7,GL_RELATIVE_RECT_NV)
+GL_ENUM(0x9368,GL_FONT_GLYPHS_AVAILABLE_NV)
+GL_ENUM(0x9369,GL_FONT_TARGET_UNAVAILABLE_NV)
+GL_ENUM(0x936A,GL_FONT_UNAVAILABLE_NV)
+GL_ENUM(0x936B,GL_FONT_UNINTELLIGIBLE_NV)
+GL_ENUM(0x1A,GL_CONIC_CURVE_TO_NV)
+GL_ENUM(0x1B,GL_RELATIVE_CONIC_CURVE_TO_NV)
+GL_ENUM(0x936C,GL_STANDARD_FONT_FORMAT_NV)
+GL_ENUM(0x84E3,GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV)
+GL_ENUM(0x84E4,GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV)
+GL_ENUM(0x936D,GL_FRAGMENT_INPUT_NV)
+GL_ENUM(0xC0,GL_SHARED_EDGE_NV)
+GL_ENUM(0x0B40,GL_POLYGON_MODE_NV)
+GL_ENUM(0x2A01,GL_POLYGON_OFFSET_POINT_NV)
+GL_ENUM(0x2A02,GL_POLYGON_OFFSET_LINE_NV)
+GL_ENUM(0x1B00,GL_POINT_NV)
+GL_ENUM(0x1B01,GL_LINE_NV)
+GL_ENUM(0x1B02,GL_FILL_NV)
 GL_ENUM(0x8C46,GL_SLUMINANCE_NV)
 GL_ENUM(0x8C44,GL_SLUMINANCE_ALPHA_NV)
 GL_ENUM(0x8C47,GL_SLUMINANCE8_NV)
@@ -1353,6 +1569,20 @@
 GL_ENUM(0x8C4E,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV)
 GL_ENUM(0x8C4F,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV)
 GL_ENUM(0x88EE,GL_ETC1_SRGB8_NV)
+GL_ENUM(0x933D,GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV)
+GL_ENUM(0x933E,GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV)
+GL_ENUM(0x933F,GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV)
+GL_ENUM(0x9340,GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV)
+GL_ENUM(0x9341,GL_PROGRAMMABLE_SAMPLE_LOCATION_NV)
+GL_ENUM(0x9342,GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV)
+GL_ENUM(0x9343,GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV)
+GL_ENUM(0x825B,GL_MAX_VIEWPORTS_NV)
+GL_ENUM(0x825C,GL_VIEWPORT_SUBPIXEL_BITS_NV)
+GL_ENUM(0x825D,GL_VIEWPORT_BOUNDS_RANGE_NV)
+GL_ENUM(0x825F,GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV)
+GL_ENUM(0x9630,GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR)
+GL_ENUM(0x9632,GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR)
+GL_ENUM(0x9631,GL_MAX_VIEWS_OVR)
 GL_ENUM(0x8FB0,GL_BINNING_CONTROL_HINT_QCOM)
 GL_ENUM(0x8FB1,GL_CPU_OPTIMIZED_QCOM)
 GL_ENUM(0x8FB2,GL_GPU_OPTIMIZED_QCOM)
diff --git a/opengl/libs/glestrace.h b/opengl/libs/glestrace.h
deleted file mode 100644
index 868b18d..0000000
--- a/opengl/libs/glestrace.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- *
- * This file declares the API provided by the glestrace library.
- */
-
-#ifndef _GLES_TRACE_H_
-#define _GLES_TRACE_H_
-
-#include "hooks.h"
-
-namespace android {
-
-/* Hooks to be called by "interesting" EGL functions. */
-void GLTrace_eglCreateContext(int version, EGLContext c);
-void GLTrace_eglMakeCurrent(unsigned version, gl_hooks_t *hooks, EGLContext c);
-void GLTrace_eglReleaseThread();
-void GLTrace_eglSwapBuffers(void*, void*);
-
-/* Start and stop GL Tracing. */
-int GLTrace_start();
-void GLTrace_stop();
-
-/* Obtain the gl_hooks structure filled with the trace implementation for all GL functions. */
-gl_hooks_t *GLTrace_getGLHooks();
-
-};
-
-#endif
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 3f36b7d..e14075c 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -31,6 +31,7 @@
 #include <GLES2/gl2ext.h>
 #include <GLES3/gl3.h>
 #include <GLES3/gl31.h>
+#include <GLES3/gl32.h>
 
 // set to 1 for debugging
 #define USE_SLOW_BINDING    0
diff --git a/opengl/libs/tools/genfiles b/opengl/libs/tools/genfiles
index a4a1958..feef318 100755
--- a/opengl/libs/tools/genfiles
+++ b/opengl/libs/tools/genfiles
@@ -40,8 +40,6 @@
         | awk -F, '!_[$2]++' \
             > ../entries.in
 
-./gltracegen ../entries.in >../trace.in
-
 cat ../../include/GLES/gl.h \
     ../../include/GLES/glext.h \
     ../../include/GLES2/gl2ext.h \
diff --git a/opengl/libs/tools/gltracegen b/opengl/libs/tools/gltracegen
deleted file mode 100755
index da42653..0000000
--- a/opengl/libs/tools/gltracegen
+++ /dev/null
@@ -1,95 +0,0 @@
-#! /usr/bin/perl
-#
-# Copyright (C) 2010 Google 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.
-
-use strict;
-
-sub rtrim($)
-{
-    my $string = shift;
-    $string =~ s/\s+$//;
-    return $string;
-}
-
-while (my $line = <>) {
-  next if $line =~ /^\//;
-  next if $line =~ /^#/;
-  next if $line =~ /^\s*$/;
-  if ($line !~ /^GL_ENTRY\(([^,]+), ([^,]+), ([^\)]+)\)/) {
-    next;
-  }
-  my $type = $1;
-  my $name = $2;
-  my $args = $3;
-  
-  my @args = split ',', $args;
-  my $len = scalar(@args);
-  my $nonVoidArgLen = 0;
-  for (my $num = 0; $num < $len; $num++) {
-    if ($args[$num] ne "void") {
-      $nonVoidArgLen++;
-    }
-  }
-  if ($type eq "void") {
-    printf("TRACE_GL_VOID(");
-  } else {
-    printf("TRACE_GL(%s, ", $type);
-  }
-  
-  printf("%s, (%s), (", $name, $args);
-    for (my $num = 0; $num < $len; $num++) {
-    if ($args[$num] ne "void") {
-      if ($num > 0) {
-        print ", ";
-      }
-      #
-      # extract the name from the parameter
-      # type name
-      # const type *name
-      # type *name
-      # type name[4]
-      #
-      if ($args[$num] =~ /(\S+\s)+\**\s*([\w]+)/) {
-        printf("%s", $2);
-      }
-    }
-  }
-  printf("), %d", $nonVoidArgLen);
-  for (my $num = 0; $num < $len; $num++) {
-    if ($args[$num] ne "void") {
-      #
-      # extract the name from the parameter
-      # type name
-      # const type *name
-      # type *name
-      # type name[4]
-      #
-      my $arg = $args[$num];
-      if ($arg =~ /(\S+\s)+\**\s*([\w]+)/) {
-        my $name = $2;
-        if ($arg =~ /((const )*(\S+\s)+\**)\s*([\w]+)/) {
-          my $type = rtrim($1);
-          printf(", \"%s\", %s", $type, $name);
-        }
-      }
-    }
-  }
-  printf(")\n");
-}
-
-
-
-
-
diff --git a/opengl/libs/trace.in b/opengl/libs/trace.in
deleted file mode 100644
index 4375a94..0000000
--- a/opengl/libs/trace.in
+++ /dev/null
@@ -1,732 +0,0 @@
-TRACE_GL_VOID(glActiveShaderProgram, (GLuint pipeline, GLuint program), (pipeline, program), 2, "GLuint", pipeline, "GLuint", program)
-TRACE_GL_VOID(glActiveShaderProgramEXT, (GLuint pipeline, GLuint program), (pipeline, program), 2, "GLuint", pipeline, "GLuint", program)
-TRACE_GL_VOID(glActiveTexture, (GLenum texture), (texture), 1, "GLenum", texture)
-TRACE_GL_VOID(glAlphaFunc, (GLenum func, GLfloat ref), (func, ref), 2, "GLenum", func, "GLfloat", ref)
-TRACE_GL_VOID(glAlphaFuncQCOM, (GLenum func, GLclampf ref), (func, ref), 2, "GLenum", func, "GLclampf", ref)
-TRACE_GL_VOID(glAlphaFuncx, (GLenum func, GLfixed ref), (func, ref), 2, "GLenum", func, "GLfixed", ref)
-TRACE_GL_VOID(glAlphaFuncxOES, (GLenum func, GLfixed ref), (func, ref), 2, "GLenum", func, "GLfixed", ref)
-TRACE_GL_VOID(glAttachShader, (GLuint program, GLuint shader), (program, shader), 2, "GLuint", program, "GLuint", shader)
-TRACE_GL_VOID(glBeginPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
-TRACE_GL_VOID(glBeginPerfQueryINTEL, (GLuint queryHandle), (queryHandle), 1, "GLuint", queryHandle)
-TRACE_GL_VOID(glBeginQuery, (GLenum target, GLuint id), (target, id), 2, "GLenum", target, "GLuint", id)
-TRACE_GL_VOID(glBeginQueryEXT, (GLenum target, GLuint id), (target, id), 2, "GLenum", target, "GLuint", id)
-TRACE_GL_VOID(glBeginTransformFeedback, (GLenum primitiveMode), (primitiveMode), 1, "GLenum", primitiveMode)
-TRACE_GL_VOID(glBindAttribLocation, (GLuint program, GLuint index, const GLchar * name), (program, index, name), 3, "GLuint", program, "GLuint", index, "const GLchar *", name)
-TRACE_GL_VOID(glBindBuffer, (GLenum target, GLuint buffer), (target, buffer), 2, "GLenum", target, "GLuint", buffer)
-TRACE_GL_VOID(glBindBufferBase, (GLenum target, GLuint index, GLuint buffer), (target, index, buffer), 3, "GLenum", target, "GLuint", index, "GLuint", buffer)
-TRACE_GL_VOID(glBindBufferRange, (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size), (target, index, buffer, offset, size), 5, "GLenum", target, "GLuint", index, "GLuint", buffer, "GLintptr", offset, "GLsizeiptr", size)
-TRACE_GL_VOID(glBindFramebuffer, (GLenum target, GLuint framebuffer), (target, framebuffer), 2, "GLenum", target, "GLuint", framebuffer)
-TRACE_GL_VOID(glBindFramebufferOES, (GLenum target, GLuint framebuffer), (target, framebuffer), 2, "GLenum", target, "GLuint", framebuffer)
-TRACE_GL_VOID(glBindImageTexture, (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), (unit, texture, level, layered, layer, access, format), 7, "GLuint", unit, "GLuint", texture, "GLint", level, "GLboolean", layered, "GLint", layer, "GLenum", access, "GLenum", format)
-TRACE_GL_VOID(glBindProgramPipeline, (GLuint pipeline), (pipeline), 1, "GLuint", pipeline)
-TRACE_GL_VOID(glBindProgramPipelineEXT, (GLuint pipeline), (pipeline), 1, "GLuint", pipeline)
-TRACE_GL_VOID(glBindRenderbuffer, (GLenum target, GLuint renderbuffer), (target, renderbuffer), 2, "GLenum", target, "GLuint", renderbuffer)
-TRACE_GL_VOID(glBindRenderbufferOES, (GLenum target, GLuint renderbuffer), (target, renderbuffer), 2, "GLenum", target, "GLuint", renderbuffer)
-TRACE_GL_VOID(glBindSampler, (GLuint unit, GLuint sampler), (unit, sampler), 2, "GLuint", unit, "GLuint", sampler)
-TRACE_GL_VOID(glBindTexture, (GLenum target, GLuint texture), (target, texture), 2, "GLenum", target, "GLuint", texture)
-TRACE_GL_VOID(glBindTransformFeedback, (GLenum target, GLuint id), (target, id), 2, "GLenum", target, "GLuint", id)
-TRACE_GL_VOID(glBindVertexArray, (GLuint array), (array), 1, "GLuint", array)
-TRACE_GL_VOID(glBindVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
-TRACE_GL_VOID(glBindVertexBuffer, (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride), (bindingindex, buffer, offset, stride), 4, "GLuint", bindingindex, "GLuint", buffer, "GLintptr", offset, "GLsizei", stride)
-TRACE_GL_VOID(glBlendBarrierKHR, (void), (), 0)
-TRACE_GL_VOID(glBlendBarrierNV, (void), (), 0)
-TRACE_GL_VOID(glBlendColor, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), (red, green, blue, alpha), 4, "GLfloat", red, "GLfloat", green, "GLfloat", blue, "GLfloat", alpha)
-TRACE_GL_VOID(glBlendEquation, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glBlendEquationOES, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glBlendEquationSeparate, (GLenum modeRGB, GLenum modeAlpha), (modeRGB, modeAlpha), 2, "GLenum", modeRGB, "GLenum", modeAlpha)
-TRACE_GL_VOID(glBlendEquationSeparateOES, (GLenum modeRGB, GLenum modeAlpha), (modeRGB, modeAlpha), 2, "GLenum", modeRGB, "GLenum", modeAlpha)
-TRACE_GL_VOID(glBlendEquationSeparateiEXT, (GLuint buf, GLenum modeRGB, GLenum modeAlpha), (buf, modeRGB, modeAlpha), 3, "GLuint", buf, "GLenum", modeRGB, "GLenum", modeAlpha)
-TRACE_GL_VOID(glBlendEquationiEXT, (GLuint buf, GLenum mode), (buf, mode), 2, "GLuint", buf, "GLenum", mode)
-TRACE_GL_VOID(glBlendFunc, (GLenum sfactor, GLenum dfactor), (sfactor, dfactor), 2, "GLenum", sfactor, "GLenum", dfactor)
-TRACE_GL_VOID(glBlendFuncSeparate, (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha), (sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha), 4, "GLenum", sfactorRGB, "GLenum", dfactorRGB, "GLenum", sfactorAlpha, "GLenum", dfactorAlpha)
-TRACE_GL_VOID(glBlendFuncSeparateOES, (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha), (srcRGB, dstRGB, srcAlpha, dstAlpha), 4, "GLenum", srcRGB, "GLenum", dstRGB, "GLenum", srcAlpha, "GLenum", dstAlpha)
-TRACE_GL_VOID(glBlendFuncSeparateiEXT, (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha), (buf, srcRGB, dstRGB, srcAlpha, dstAlpha), 5, "GLuint", buf, "GLenum", srcRGB, "GLenum", dstRGB, "GLenum", srcAlpha, "GLenum", dstAlpha)
-TRACE_GL_VOID(glBlendFunciEXT, (GLuint buf, GLenum src, GLenum dst), (buf, src, dst), 3, "GLuint", buf, "GLenum", src, "GLenum", dst)
-TRACE_GL_VOID(glBlendParameteriNV, (GLenum pname, GLint value), (pname, value), 2, "GLenum", pname, "GLint", value)
-TRACE_GL_VOID(glBlitFramebuffer, (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter), (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), 10, "GLint", srcX0, "GLint", srcY0, "GLint", srcX1, "GLint", srcY1, "GLint", dstX0, "GLint", dstY0, "GLint", dstX1, "GLint", dstY1, "GLbitfield", mask, "GLenum", filter)
-TRACE_GL_VOID(glBlitFramebufferANGLE, (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter), (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), 10, "GLint", srcX0, "GLint", srcY0, "GLint", srcX1, "GLint", srcY1, "GLint", dstX0, "GLint", dstY0, "GLint", dstX1, "GLint", dstY1, "GLbitfield", mask, "GLenum", filter)
-TRACE_GL_VOID(glBlitFramebufferNV, (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter), (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter), 10, "GLint", srcX0, "GLint", srcY0, "GLint", srcX1, "GLint", srcY1, "GLint", dstX0, "GLint", dstY0, "GLint", dstX1, "GLint", dstY1, "GLbitfield", mask, "GLenum", filter)
-TRACE_GL_VOID(glBufferData, (GLenum target, GLsizeiptr size, const void * data, GLenum usage), (target, size, data, usage), 4, "GLenum", target, "GLsizeiptr", size, "const void *", data, "GLenum", usage)
-TRACE_GL_VOID(glBufferSubData, (GLenum target, GLintptr offset, GLsizeiptr size, const void * data), (target, offset, size, data), 4, "GLenum", target, "GLintptr", offset, "GLsizeiptr", size, "const void *", data)
-TRACE_GL(GLenum, glCheckFramebufferStatus, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL(GLenum, glCheckFramebufferStatusOES, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL_VOID(glClear, (GLbitfield mask), (mask), 1, "GLbitfield", mask)
-TRACE_GL_VOID(glClearBufferfi, (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil), (buffer, drawbuffer, depth, stencil), 4, "GLenum", buffer, "GLint", drawbuffer, "GLfloat", depth, "GLint", stencil)
-TRACE_GL_VOID(glClearBufferfv, (GLenum buffer, GLint drawbuffer, const GLfloat * value), (buffer, drawbuffer, value), 3, "GLenum", buffer, "GLint", drawbuffer, "const GLfloat *", value)
-TRACE_GL_VOID(glClearBufferiv, (GLenum buffer, GLint drawbuffer, const GLint * value), (buffer, drawbuffer, value), 3, "GLenum", buffer, "GLint", drawbuffer, "const GLint *", value)
-TRACE_GL_VOID(glClearBufferuiv, (GLenum buffer, GLint drawbuffer, const GLuint * value), (buffer, drawbuffer, value), 3, "GLenum", buffer, "GLint", drawbuffer, "const GLuint *", value)
-TRACE_GL_VOID(glClearColor, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), (red, green, blue, alpha), 4, "GLfloat", red, "GLfloat", green, "GLfloat", blue, "GLfloat", alpha)
-TRACE_GL_VOID(glClearColorx, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
-TRACE_GL_VOID(glClearColorxOES, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
-TRACE_GL_VOID(glClearDepthf, (GLfloat d), (d), 1, "GLfloat", d)
-TRACE_GL_VOID(glClearDepthfOES, (GLclampf depth), (depth), 1, "GLclampf", depth)
-TRACE_GL_VOID(glClearDepthx, (GLfixed depth), (depth), 1, "GLfixed", depth)
-TRACE_GL_VOID(glClearDepthxOES, (GLfixed depth), (depth), 1, "GLfixed", depth)
-TRACE_GL_VOID(glClearStencil, (GLint s), (s), 1, "GLint", s)
-TRACE_GL_VOID(glClientActiveTexture, (GLenum texture), (texture), 1, "GLenum", texture)
-TRACE_GL(GLenum, glClientWaitSync, (GLsync sync, GLbitfield flags, GLuint64 timeout), (sync, flags, timeout), 3, "GLsync", sync, "GLbitfield", flags, "GLuint64", timeout)
-TRACE_GL(GLenum, glClientWaitSyncAPPLE, (GLsync sync, GLbitfield flags, GLuint64 timeout), (sync, flags, timeout), 3, "GLsync", sync, "GLbitfield", flags, "GLuint64", timeout)
-TRACE_GL_VOID(glClipPlanef, (GLenum p, const GLfloat * eqn), (p, eqn), 2, "GLenum", p, "const GLfloat *", eqn)
-TRACE_GL_VOID(glClipPlanefIMG, (GLenum p, const GLfloat * eqn), (p, eqn), 2, "GLenum", p, "const GLfloat *", eqn)
-TRACE_GL_VOID(glClipPlanefOES, (GLenum plane, const GLfloat * equation), (plane, equation), 2, "GLenum", plane, "const GLfloat *", equation)
-TRACE_GL_VOID(glClipPlanex, (GLenum plane, const GLfixed * equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
-TRACE_GL_VOID(glClipPlanexIMG, (GLenum p, const GLfixed * eqn), (p, eqn), 2, "GLenum", p, "const GLfixed *", eqn)
-TRACE_GL_VOID(glClipPlanexOES, (GLenum plane, const GLfixed * equation), (plane, equation), 2, "GLenum", plane, "const GLfixed *", equation)
-TRACE_GL_VOID(glColor4f, (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha), (red, green, blue, alpha), 4, "GLfloat", red, "GLfloat", green, "GLfloat", blue, "GLfloat", alpha)
-TRACE_GL_VOID(glColor4ub, (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha), (red, green, blue, alpha), 4, "GLubyte", red, "GLubyte", green, "GLubyte", blue, "GLubyte", alpha)
-TRACE_GL_VOID(glColor4x, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
-TRACE_GL_VOID(glColor4xOES, (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha), (red, green, blue, alpha), 4, "GLfixed", red, "GLfixed", green, "GLfixed", blue, "GLfixed", alpha)
-TRACE_GL_VOID(glColorMask, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha), (red, green, blue, alpha), 4, "GLboolean", red, "GLboolean", green, "GLboolean", blue, "GLboolean", alpha)
-TRACE_GL_VOID(glColorMaskiEXT, (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a), (index, r, g, b, a), 5, "GLuint", index, "GLboolean", r, "GLboolean", g, "GLboolean", b, "GLboolean", a)
-TRACE_GL_VOID(glColorPointer, (GLint size, GLenum type, GLsizei stride, const void * pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glCompileShader, (GLuint shader), (shader), 1, "GLuint", shader)
-TRACE_GL_VOID(glCompressedTexImage2D, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data), (target, level, internalformat, width, height, border, imageSize, data), 8, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLint", border, "GLsizei", imageSize, "const void *", data)
-TRACE_GL_VOID(glCompressedTexImage3D, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data), (target, level, internalformat, width, height, depth, border, imageSize, data), 9, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLsizei", imageSize, "const void *", data)
-TRACE_GL_VOID(glCompressedTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data), (target, level, internalformat, width, height, depth, border, imageSize, data), 9, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLsizei", imageSize, "const void *", data)
-TRACE_GL_VOID(glCompressedTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data), (target, level, xoffset, yoffset, width, height, format, imageSize, data), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLsizei", imageSize, "const void *", data)
-TRACE_GL_VOID(glCompressedTexSubImage3D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLsizei", imageSize, "const void *", data)
-TRACE_GL_VOID(glCompressedTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLsizei", imageSize, "const void *", data)
-TRACE_GL_VOID(glCopyBufferSubData, (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size), (readTarget, writeTarget, readOffset, writeOffset, size), 5, "GLenum", readTarget, "GLenum", writeTarget, "GLintptr", readOffset, "GLintptr", writeOffset, "GLsizeiptr", size)
-TRACE_GL_VOID(glCopyBufferSubDataNV, (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size), (readTarget, writeTarget, readOffset, writeOffset, size), 5, "GLenum", readTarget, "GLenum", writeTarget, "GLintptr", readOffset, "GLintptr", writeOffset, "GLsizeiptr", size)
-TRACE_GL_VOID(glCopyImageSubDataEXT, (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth), (srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth), 15, "GLuint", srcName, "GLenum", srcTarget, "GLint", srcLevel, "GLint", srcX, "GLint", srcY, "GLint", srcZ, "GLuint", dstName, "GLenum", dstTarget, "GLint", dstLevel, "GLint", dstX, "GLint", dstY, "GLint", dstZ, "GLsizei", srcWidth, "GLsizei", srcHeight, "GLsizei", srcDepth)
-TRACE_GL_VOID(glCopyTexImage2D, (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border), (target, level, internalformat, x, y, width, height, border), 8, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height, "GLint", border)
-TRACE_GL_VOID(glCopyTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, x, y, width, height), 8, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glCopyTexSubImage3D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, zoffset, x, y, width, height), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glCopyTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height), (target, level, xoffset, yoffset, zoffset, x, y, width, height), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glCopyTextureLevelsAPPLE, (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount), (destinationTexture, sourceTexture, sourceBaseLevel, sourceLevelCount), 4, "GLuint", destinationTexture, "GLuint", sourceTexture, "GLint", sourceBaseLevel, "GLsizei", sourceLevelCount)
-TRACE_GL_VOID(glCoverageMaskNV, (GLboolean mask), (mask), 1, "GLboolean", mask)
-TRACE_GL_VOID(glCoverageOperationNV, (GLenum operation), (operation), 1, "GLenum", operation)
-TRACE_GL_VOID(glCreatePerfQueryINTEL, (GLuint queryId, GLuint * queryHandle), (queryId, queryHandle), 2, "GLuint", queryId, "GLuint *", queryHandle)
-TRACE_GL(GLuint, glCreateProgram, (void), (), 0)
-TRACE_GL(GLuint, glCreateShader, (GLenum type), (type), 1, "GLenum", type)
-TRACE_GL(GLuint, glCreateShaderProgramv, (GLenum type, GLsizei count, const GLchar *const* strings), (type, count, strings), 3, "GLenum", type, "GLsizei", count, "const GLchar *const*", strings)
-TRACE_GL(GLuint, glCreateShaderProgramvEXT, (GLenum type, GLsizei count, const GLchar ** strings), (type, count, strings), 3, "GLenum", type, "GLsizei", count, "const GLchar **", strings)
-TRACE_GL_VOID(glCullFace, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glCurrentPaletteMatrixOES, (GLuint matrixpaletteindex), (matrixpaletteindex), 1, "GLuint", matrixpaletteindex)
-TRACE_GL_VOID(glDebugMessageCallbackKHR, (GLDEBUGPROCKHR callback, const void * userParam), (callback, userParam), 2, "GLDEBUGPROCKHR", callback, "const void *", userParam)
-TRACE_GL_VOID(glDebugMessageControlKHR, (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled), (source, type, severity, count, ids, enabled), 6, "GLenum", source, "GLenum", type, "GLenum", severity, "GLsizei", count, "const GLuint *", ids, "GLboolean", enabled)
-TRACE_GL_VOID(glDebugMessageInsertKHR, (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf), (source, type, id, severity, length, buf), 6, "GLenum", source, "GLenum", type, "GLuint", id, "GLenum", severity, "GLsizei", length, "const GLchar *", buf)
-TRACE_GL_VOID(glDeleteBuffers, (GLsizei n, const GLuint * buffers), (n, buffers), 2, "GLsizei", n, "const GLuint *", buffers)
-TRACE_GL_VOID(glDeleteFencesNV, (GLsizei n, const GLuint * fences), (n, fences), 2, "GLsizei", n, "const GLuint *", fences)
-TRACE_GL_VOID(glDeleteFramebuffers, (GLsizei n, const GLuint * framebuffers), (n, framebuffers), 2, "GLsizei", n, "const GLuint *", framebuffers)
-TRACE_GL_VOID(glDeleteFramebuffersOES, (GLsizei n, const GLuint * framebuffers), (n, framebuffers), 2, "GLsizei", n, "const GLuint *", framebuffers)
-TRACE_GL_VOID(glDeletePerfMonitorsAMD, (GLsizei n, GLuint * monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
-TRACE_GL_VOID(glDeletePerfQueryINTEL, (GLuint queryHandle), (queryHandle), 1, "GLuint", queryHandle)
-TRACE_GL_VOID(glDeleteProgram, (GLuint program), (program), 1, "GLuint", program)
-TRACE_GL_VOID(glDeleteProgramPipelines, (GLsizei n, const GLuint * pipelines), (n, pipelines), 2, "GLsizei", n, "const GLuint *", pipelines)
-TRACE_GL_VOID(glDeleteProgramPipelinesEXT, (GLsizei n, const GLuint * pipelines), (n, pipelines), 2, "GLsizei", n, "const GLuint *", pipelines)
-TRACE_GL_VOID(glDeleteQueries, (GLsizei n, const GLuint * ids), (n, ids), 2, "GLsizei", n, "const GLuint *", ids)
-TRACE_GL_VOID(glDeleteQueriesEXT, (GLsizei n, const GLuint * ids), (n, ids), 2, "GLsizei", n, "const GLuint *", ids)
-TRACE_GL_VOID(glDeleteRenderbuffers, (GLsizei n, const GLuint * renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "const GLuint *", renderbuffers)
-TRACE_GL_VOID(glDeleteRenderbuffersOES, (GLsizei n, const GLuint * renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "const GLuint *", renderbuffers)
-TRACE_GL_VOID(glDeleteSamplers, (GLsizei count, const GLuint * samplers), (count, samplers), 2, "GLsizei", count, "const GLuint *", samplers)
-TRACE_GL_VOID(glDeleteShader, (GLuint shader), (shader), 1, "GLuint", shader)
-TRACE_GL_VOID(glDeleteSync, (GLsync sync), (sync), 1, "GLsync", sync)
-TRACE_GL_VOID(glDeleteSyncAPPLE, (GLsync sync), (sync), 1, "GLsync", sync)
-TRACE_GL_VOID(glDeleteTextures, (GLsizei n, const GLuint * textures), (n, textures), 2, "GLsizei", n, "const GLuint *", textures)
-TRACE_GL_VOID(glDeleteTransformFeedbacks, (GLsizei n, const GLuint * ids), (n, ids), 2, "GLsizei", n, "const GLuint *", ids)
-TRACE_GL_VOID(glDeleteVertexArrays, (GLsizei n, const GLuint * arrays), (n, arrays), 2, "GLsizei", n, "const GLuint *", arrays)
-TRACE_GL_VOID(glDeleteVertexArraysOES, (GLsizei n, const GLuint * arrays), (n, arrays), 2, "GLsizei", n, "const GLuint *", arrays)
-TRACE_GL_VOID(glDepthFunc, (GLenum func), (func), 1, "GLenum", func)
-TRACE_GL_VOID(glDepthMask, (GLboolean flag), (flag), 1, "GLboolean", flag)
-TRACE_GL_VOID(glDepthRangef, (GLfloat n, GLfloat f), (n, f), 2, "GLfloat", n, "GLfloat", f)
-TRACE_GL_VOID(glDepthRangefOES, (GLclampf n, GLclampf f), (n, f), 2, "GLclampf", n, "GLclampf", f)
-TRACE_GL_VOID(glDepthRangex, (GLfixed n, GLfixed f), (n, f), 2, "GLfixed", n, "GLfixed", f)
-TRACE_GL_VOID(glDepthRangexOES, (GLfixed n, GLfixed f), (n, f), 2, "GLfixed", n, "GLfixed", f)
-TRACE_GL_VOID(glDetachShader, (GLuint program, GLuint shader), (program, shader), 2, "GLuint", program, "GLuint", shader)
-TRACE_GL_VOID(glDisable, (GLenum cap), (cap), 1, "GLenum", cap)
-TRACE_GL_VOID(glDisableClientState, (GLenum array), (array), 1, "GLenum", array)
-TRACE_GL_VOID(glDisableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
-TRACE_GL_VOID(glDisableVertexAttribArray, (GLuint index), (index), 1, "GLuint", index)
-TRACE_GL_VOID(glDisableiEXT, (GLenum target, GLuint index), (target, index), 2, "GLenum", target, "GLuint", index)
-TRACE_GL_VOID(glDiscardFramebufferEXT, (GLenum target, GLsizei numAttachments, const GLenum * attachments), (target, numAttachments, attachments), 3, "GLenum", target, "GLsizei", numAttachments, "const GLenum *", attachments)
-TRACE_GL_VOID(glDispatchCompute, (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z), (num_groups_x, num_groups_y, num_groups_z), 3, "GLuint", num_groups_x, "GLuint", num_groups_y, "GLuint", num_groups_z)
-TRACE_GL_VOID(glDispatchComputeIndirect, (GLintptr indirect), (indirect), 1, "GLintptr", indirect)
-TRACE_GL_VOID(glDrawArrays, (GLenum mode, GLint first, GLsizei count), (mode, first, count), 3, "GLenum", mode, "GLint", first, "GLsizei", count)
-TRACE_GL_VOID(glDrawArraysIndirect, (GLenum mode, const void * indirect), (mode, indirect), 2, "GLenum", mode, "const void *", indirect)
-TRACE_GL_VOID(glDrawArraysInstanced, (GLenum mode, GLint first, GLsizei count, GLsizei instancecount), (mode, first, count, instancecount), 4, "GLenum", mode, "GLint", first, "GLsizei", count, "GLsizei", instancecount)
-TRACE_GL_VOID(glDrawArraysInstancedANGLE, (GLenum mode, GLint first, GLsizei count, GLsizei primcount), (mode, first, count, primcount), 4, "GLenum", mode, "GLint", first, "GLsizei", count, "GLsizei", primcount)
-TRACE_GL_VOID(glDrawArraysInstancedEXT, (GLenum mode, GLint start, GLsizei count, GLsizei primcount), (mode, start, count, primcount), 4, "GLenum", mode, "GLint", start, "GLsizei", count, "GLsizei", primcount)
-TRACE_GL_VOID(glDrawArraysInstancedNV, (GLenum mode, GLint first, GLsizei count, GLsizei primcount), (mode, first, count, primcount), 4, "GLenum", mode, "GLint", first, "GLsizei", count, "GLsizei", primcount)
-TRACE_GL_VOID(glDrawBuffers, (GLsizei n, const GLenum * bufs), (n, bufs), 2, "GLsizei", n, "const GLenum *", bufs)
-TRACE_GL_VOID(glDrawBuffersEXT, (GLsizei n, const GLenum * bufs), (n, bufs), 2, "GLsizei", n, "const GLenum *", bufs)
-TRACE_GL_VOID(glDrawBuffersIndexedEXT, (GLint n, const GLenum * location, const GLint * indices), (n, location, indices), 3, "GLint", n, "const GLenum *", location, "const GLint *", indices)
-TRACE_GL_VOID(glDrawBuffersNV, (GLsizei n, const GLenum * bufs), (n, bufs), 2, "GLsizei", n, "const GLenum *", bufs)
-TRACE_GL_VOID(glDrawElements, (GLenum mode, GLsizei count, GLenum type, const void * indices), (mode, count, type, indices), 4, "GLenum", mode, "GLsizei", count, "GLenum", type, "const void *", indices)
-TRACE_GL_VOID(glDrawElementsIndirect, (GLenum mode, GLenum type, const void * indirect), (mode, type, indirect), 3, "GLenum", mode, "GLenum", type, "const void *", indirect)
-TRACE_GL_VOID(glDrawElementsInstanced, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount), (mode, count, type, indices, instancecount), 5, "GLenum", mode, "GLsizei", count, "GLenum", type, "const void *", indices, "GLsizei", instancecount)
-TRACE_GL_VOID(glDrawElementsInstancedANGLE, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "GLsizei", count, "GLenum", type, "const void *", indices, "GLsizei", primcount)
-TRACE_GL_VOID(glDrawElementsInstancedEXT, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "GLsizei", count, "GLenum", type, "const void *", indices, "GLsizei", primcount)
-TRACE_GL_VOID(glDrawElementsInstancedNV, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "GLsizei", count, "GLenum", type, "const void *", indices, "GLsizei", primcount)
-TRACE_GL_VOID(glDrawRangeElements, (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices), (mode, start, end, count, type, indices), 6, "GLenum", mode, "GLuint", start, "GLuint", end, "GLsizei", count, "GLenum", type, "const void *", indices)
-TRACE_GL_VOID(glDrawTexfOES, (GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height), (x, y, z, width, height), 5, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", width, "GLfloat", height)
-TRACE_GL_VOID(glDrawTexfvOES, (const GLfloat * coords), (coords), 1, "const GLfloat *", coords)
-TRACE_GL_VOID(glDrawTexiOES, (GLint x, GLint y, GLint z, GLint width, GLint height), (x, y, z, width, height), 5, "GLint", x, "GLint", y, "GLint", z, "GLint", width, "GLint", height)
-TRACE_GL_VOID(glDrawTexivOES, (const GLint * coords), (coords), 1, "const GLint *", coords)
-TRACE_GL_VOID(glDrawTexsOES, (GLshort x, GLshort y, GLshort z, GLshort width, GLshort height), (x, y, z, width, height), 5, "GLshort", x, "GLshort", y, "GLshort", z, "GLshort", width, "GLshort", height)
-TRACE_GL_VOID(glDrawTexsvOES, (const GLshort * coords), (coords), 1, "const GLshort *", coords)
-TRACE_GL_VOID(glDrawTexxOES, (GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height), (x, y, z, width, height), 5, "GLfixed", x, "GLfixed", y, "GLfixed", z, "GLfixed", width, "GLfixed", height)
-TRACE_GL_VOID(glDrawTexxvOES, (const GLfixed * coords), (coords), 1, "const GLfixed *", coords)
-TRACE_GL_VOID(glEGLImageTargetRenderbufferStorageOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
-TRACE_GL_VOID(glEGLImageTargetTexture2DOES, (GLenum target, GLeglImageOES image), (target, image), 2, "GLenum", target, "GLeglImageOES", image)
-TRACE_GL_VOID(glEnable, (GLenum cap), (cap), 1, "GLenum", cap)
-TRACE_GL_VOID(glEnableClientState, (GLenum array), (array), 1, "GLenum", array)
-TRACE_GL_VOID(glEnableDriverControlQCOM, (GLuint driverControl), (driverControl), 1, "GLuint", driverControl)
-TRACE_GL_VOID(glEnableVertexAttribArray, (GLuint index), (index), 1, "GLuint", index)
-TRACE_GL_VOID(glEnableiEXT, (GLenum target, GLuint index), (target, index), 2, "GLenum", target, "GLuint", index)
-TRACE_GL_VOID(glEndPerfMonitorAMD, (GLuint monitor), (monitor), 1, "GLuint", monitor)
-TRACE_GL_VOID(glEndPerfQueryINTEL, (GLuint queryHandle), (queryHandle), 1, "GLuint", queryHandle)
-TRACE_GL_VOID(glEndQuery, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL_VOID(glEndQueryEXT, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL_VOID(glEndTilingQCOM, (GLbitfield preserveMask), (preserveMask), 1, "GLbitfield", preserveMask)
-TRACE_GL_VOID(glEndTransformFeedback, (void), (), 0)
-TRACE_GL_VOID(glExtGetBufferPointervQCOM, (GLenum target, void ** params), (target, params), 2, "GLenum", target, "void **", params)
-TRACE_GL_VOID(glExtGetBuffersQCOM, (GLuint * buffers, GLint maxBuffers, GLint * numBuffers), (buffers, maxBuffers, numBuffers), 3, "GLuint *", buffers, "GLint", maxBuffers, "GLint *", numBuffers)
-TRACE_GL_VOID(glExtGetFramebuffersQCOM, (GLuint * framebuffers, GLint maxFramebuffers, GLint * numFramebuffers), (framebuffers, maxFramebuffers, numFramebuffers), 3, "GLuint *", framebuffers, "GLint", maxFramebuffers, "GLint *", numFramebuffers)
-TRACE_GL_VOID(glExtGetProgramBinarySourceQCOM, (GLuint program, GLenum shadertype, GLchar * source, GLint * length), (program, shadertype, source, length), 4, "GLuint", program, "GLenum", shadertype, "GLchar *", source, "GLint *", length)
-TRACE_GL_VOID(glExtGetProgramsQCOM, (GLuint * programs, GLint maxPrograms, GLint * numPrograms), (programs, maxPrograms, numPrograms), 3, "GLuint *", programs, "GLint", maxPrograms, "GLint *", numPrograms)
-TRACE_GL_VOID(glExtGetRenderbuffersQCOM, (GLuint * renderbuffers, GLint maxRenderbuffers, GLint * numRenderbuffers), (renderbuffers, maxRenderbuffers, numRenderbuffers), 3, "GLuint *", renderbuffers, "GLint", maxRenderbuffers, "GLint *", numRenderbuffers)
-TRACE_GL_VOID(glExtGetShadersQCOM, (GLuint * shaders, GLint maxShaders, GLint * numShaders), (shaders, maxShaders, numShaders), 3, "GLuint *", shaders, "GLint", maxShaders, "GLint *", numShaders)
-TRACE_GL_VOID(glExtGetTexLevelParameterivQCOM, (GLuint texture, GLenum face, GLint level, GLenum pname, GLint * params), (texture, face, level, pname, params), 5, "GLuint", texture, "GLenum", face, "GLint", level, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glExtGetTexSubImageQCOM, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void * texels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "void *", texels)
-TRACE_GL_VOID(glExtGetTexturesQCOM, (GLuint * textures, GLint maxTextures, GLint * numTextures), (textures, maxTextures, numTextures), 3, "GLuint *", textures, "GLint", maxTextures, "GLint *", numTextures)
-TRACE_GL(GLboolean, glExtIsProgramBinaryQCOM, (GLuint program), (program), 1, "GLuint", program)
-TRACE_GL_VOID(glExtTexObjectStateOverrideiQCOM, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
-TRACE_GL(GLsync, glFenceSync, (GLenum condition, GLbitfield flags), (condition, flags), 2, "GLenum", condition, "GLbitfield", flags)
-TRACE_GL(GLsync, glFenceSyncAPPLE, (GLenum condition, GLbitfield flags), (condition, flags), 2, "GLenum", condition, "GLbitfield", flags)
-TRACE_GL_VOID(glFinish, (void), (), 0)
-TRACE_GL_VOID(glFinishFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
-TRACE_GL_VOID(glFlush, (void), (), 0)
-TRACE_GL_VOID(glFlushMappedBufferRange, (GLenum target, GLintptr offset, GLsizeiptr length), (target, offset, length), 3, "GLenum", target, "GLintptr", offset, "GLsizeiptr", length)
-TRACE_GL_VOID(glFlushMappedBufferRangeEXT, (GLenum target, GLintptr offset, GLsizeiptr length), (target, offset, length), 3, "GLenum", target, "GLintptr", offset, "GLsizeiptr", length)
-TRACE_GL_VOID(glFogf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glFogfv, (GLenum pname, const GLfloat * params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glFogx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glFogxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glFogxv, (GLenum pname, const GLfixed * param), (pname, param), 2, "GLenum", pname, "const GLfixed *", param)
-TRACE_GL_VOID(glFogxvOES, (GLenum pname, const GLfixed * param), (pname, param), 2, "GLenum", pname, "const GLfixed *", param)
-TRACE_GL_VOID(glFramebufferParameteri, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
-TRACE_GL_VOID(glFramebufferRenderbuffer, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer), 4, "GLenum", target, "GLenum", attachment, "GLenum", renderbuffertarget, "GLuint", renderbuffer)
-TRACE_GL_VOID(glFramebufferRenderbufferOES, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer), 4, "GLenum", target, "GLenum", attachment, "GLenum", renderbuffertarget, "GLuint", renderbuffer)
-TRACE_GL_VOID(glFramebufferTexture2D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level), 5, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level)
-TRACE_GL_VOID(glFramebufferTexture2DMultisampleEXT, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples), (target, attachment, textarget, texture, level, samples), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLsizei", samples)
-TRACE_GL_VOID(glFramebufferTexture2DMultisampleIMG, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples), (target, attachment, textarget, texture, level, samples), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLsizei", samples)
-TRACE_GL_VOID(glFramebufferTexture2DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level), 5, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level)
-TRACE_GL_VOID(glFramebufferTexture3DOES, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset), (target, attachment, textarget, texture, level, zoffset), 6, "GLenum", target, "GLenum", attachment, "GLenum", textarget, "GLuint", texture, "GLint", level, "GLint", zoffset)
-TRACE_GL_VOID(glFramebufferTextureEXT, (GLenum target, GLenum attachment, GLuint texture, GLint level), (target, attachment, texture, level), 4, "GLenum", target, "GLenum", attachment, "GLuint", texture, "GLint", level)
-TRACE_GL_VOID(glFramebufferTextureLayer, (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer), (target, attachment, texture, level, layer), 5, "GLenum", target, "GLenum", attachment, "GLuint", texture, "GLint", level, "GLint", layer)
-TRACE_GL_VOID(glFrontFace, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glFrustumf, (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f), (l, r, b, t, n, f), 6, "GLfloat", l, "GLfloat", r, "GLfloat", b, "GLfloat", t, "GLfloat", n, "GLfloat", f)
-TRACE_GL_VOID(glFrustumfOES, (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f), (l, r, b, t, n, f), 6, "GLfloat", l, "GLfloat", r, "GLfloat", b, "GLfloat", t, "GLfloat", n, "GLfloat", f)
-TRACE_GL_VOID(glFrustumx, (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f), (l, r, b, t, n, f), 6, "GLfixed", l, "GLfixed", r, "GLfixed", b, "GLfixed", t, "GLfixed", n, "GLfixed", f)
-TRACE_GL_VOID(glFrustumxOES, (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f), (l, r, b, t, n, f), 6, "GLfixed", l, "GLfixed", r, "GLfixed", b, "GLfixed", t, "GLfixed", n, "GLfixed", f)
-TRACE_GL_VOID(glGenBuffers, (GLsizei n, GLuint * buffers), (n, buffers), 2, "GLsizei", n, "GLuint *", buffers)
-TRACE_GL_VOID(glGenFencesNV, (GLsizei n, GLuint * fences), (n, fences), 2, "GLsizei", n, "GLuint *", fences)
-TRACE_GL_VOID(glGenFramebuffers, (GLsizei n, GLuint * framebuffers), (n, framebuffers), 2, "GLsizei", n, "GLuint *", framebuffers)
-TRACE_GL_VOID(glGenFramebuffersOES, (GLsizei n, GLuint * framebuffers), (n, framebuffers), 2, "GLsizei", n, "GLuint *", framebuffers)
-TRACE_GL_VOID(glGenPerfMonitorsAMD, (GLsizei n, GLuint * monitors), (n, monitors), 2, "GLsizei", n, "GLuint *", monitors)
-TRACE_GL_VOID(glGenProgramPipelines, (GLsizei n, GLuint * pipelines), (n, pipelines), 2, "GLsizei", n, "GLuint *", pipelines)
-TRACE_GL_VOID(glGenProgramPipelinesEXT, (GLsizei n, GLuint * pipelines), (n, pipelines), 2, "GLsizei", n, "GLuint *", pipelines)
-TRACE_GL_VOID(glGenQueries, (GLsizei n, GLuint * ids), (n, ids), 2, "GLsizei", n, "GLuint *", ids)
-TRACE_GL_VOID(glGenQueriesEXT, (GLsizei n, GLuint * ids), (n, ids), 2, "GLsizei", n, "GLuint *", ids)
-TRACE_GL_VOID(glGenRenderbuffers, (GLsizei n, GLuint * renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "GLuint *", renderbuffers)
-TRACE_GL_VOID(glGenRenderbuffersOES, (GLsizei n, GLuint * renderbuffers), (n, renderbuffers), 2, "GLsizei", n, "GLuint *", renderbuffers)
-TRACE_GL_VOID(glGenSamplers, (GLsizei count, GLuint * samplers), (count, samplers), 2, "GLsizei", count, "GLuint *", samplers)
-TRACE_GL_VOID(glGenTextures, (GLsizei n, GLuint * textures), (n, textures), 2, "GLsizei", n, "GLuint *", textures)
-TRACE_GL_VOID(glGenTransformFeedbacks, (GLsizei n, GLuint * ids), (n, ids), 2, "GLsizei", n, "GLuint *", ids)
-TRACE_GL_VOID(glGenVertexArrays, (GLsizei n, GLuint * arrays), (n, arrays), 2, "GLsizei", n, "GLuint *", arrays)
-TRACE_GL_VOID(glGenVertexArraysOES, (GLsizei n, GLuint * arrays), (n, arrays), 2, "GLsizei", n, "GLuint *", arrays)
-TRACE_GL_VOID(glGenerateMipmap, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL_VOID(glGenerateMipmapOES, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL_VOID(glGetActiveAttrib, (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name), (program, index, bufSize, length, size, type, name), 7, "GLuint", program, "GLuint", index, "GLsizei", bufSize, "GLsizei *", length, "GLint *", size, "GLenum *", type, "GLchar *", name)
-TRACE_GL_VOID(glGetActiveUniform, (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name), (program, index, bufSize, length, size, type, name), 7, "GLuint", program, "GLuint", index, "GLsizei", bufSize, "GLsizei *", length, "GLint *", size, "GLenum *", type, "GLchar *", name)
-TRACE_GL_VOID(glGetActiveUniformBlockName, (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName), (program, uniformBlockIndex, bufSize, length, uniformBlockName), 5, "GLuint", program, "GLuint", uniformBlockIndex, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", uniformBlockName)
-TRACE_GL_VOID(glGetActiveUniformBlockiv, (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params), (program, uniformBlockIndex, pname, params), 4, "GLuint", program, "GLuint", uniformBlockIndex, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetActiveUniformsiv, (GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params), (program, uniformCount, uniformIndices, pname, params), 5, "GLuint", program, "GLsizei", uniformCount, "const GLuint *", uniformIndices, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetAttachedShaders, (GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders), (program, maxCount, count, shaders), 4, "GLuint", program, "GLsizei", maxCount, "GLsizei *", count, "GLuint *", shaders)
-TRACE_GL(GLint, glGetAttribLocation, (GLuint program, const GLchar * name), (program, name), 2, "GLuint", program, "const GLchar *", name)
-TRACE_GL_VOID(glGetBooleani_v, (GLenum target, GLuint index, GLboolean * data), (target, index, data), 3, "GLenum", target, "GLuint", index, "GLboolean *", data)
-TRACE_GL_VOID(glGetBooleanv, (GLenum pname, GLboolean * data), (pname, data), 2, "GLenum", pname, "GLboolean *", data)
-TRACE_GL_VOID(glGetBufferParameteri64v, (GLenum target, GLenum pname, GLint64 * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint64 *", params)
-TRACE_GL_VOID(glGetBufferParameteriv, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetBufferPointerv, (GLenum target, GLenum pname, void ** params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "void **", params)
-TRACE_GL_VOID(glGetBufferPointervOES, (GLenum target, GLenum pname, void ** params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "void **", params)
-TRACE_GL_VOID(glGetClipPlanef, (GLenum plane, GLfloat * equation), (plane, equation), 2, "GLenum", plane, "GLfloat *", equation)
-TRACE_GL_VOID(glGetClipPlanefOES, (GLenum plane, GLfloat * equation), (plane, equation), 2, "GLenum", plane, "GLfloat *", equation)
-TRACE_GL_VOID(glGetClipPlanex, (GLenum plane, GLfixed * equation), (plane, equation), 2, "GLenum", plane, "GLfixed *", equation)
-TRACE_GL_VOID(glGetClipPlanexOES, (GLenum plane, GLfixed * equation), (plane, equation), 2, "GLenum", plane, "GLfixed *", equation)
-TRACE_GL(GLuint, glGetDebugMessageLogKHR, (GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog), (count, bufSize, sources, types, ids, severities, lengths, messageLog), 8, "GLuint", count, "GLsizei", bufSize, "GLenum *", sources, "GLenum *", types, "GLuint *", ids, "GLenum *", severities, "GLsizei *", lengths, "GLchar *", messageLog)
-TRACE_GL_VOID(glGetDriverControlStringQCOM, (GLuint driverControl, GLsizei bufSize, GLsizei * length, GLchar * driverControlString), (driverControl, bufSize, length, driverControlString), 4, "GLuint", driverControl, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", driverControlString)
-TRACE_GL_VOID(glGetDriverControlsQCOM, (GLint * num, GLsizei size, GLuint * driverControls), (num, size, driverControls), 3, "GLint *", num, "GLsizei", size, "GLuint *", driverControls)
-TRACE_GL(GLenum, glGetError, (void), (), 0)
-TRACE_GL_VOID(glGetFenceivNV, (GLuint fence, GLenum pname, GLint * params), (fence, pname, params), 3, "GLuint", fence, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetFirstPerfQueryIdINTEL, (GLuint * queryId), (queryId), 1, "GLuint *", queryId)
-TRACE_GL_VOID(glGetFixedv, (GLenum pname, GLfixed * params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetFixedvOES, (GLenum pname, GLfixed * params), (pname, params), 2, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetFloatv, (GLenum pname, GLfloat * data), (pname, data), 2, "GLenum", pname, "GLfloat *", data)
-TRACE_GL(GLint, glGetFragDataLocation, (GLuint program, const GLchar * name), (program, name), 2, "GLuint", program, "const GLchar *", name)
-TRACE_GL_VOID(glGetFramebufferAttachmentParameteriv, (GLenum target, GLenum attachment, GLenum pname, GLint * params), (target, attachment, pname, params), 4, "GLenum", target, "GLenum", attachment, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetFramebufferAttachmentParameterivOES, (GLenum target, GLenum attachment, GLenum pname, GLint * params), (target, attachment, pname, params), 4, "GLenum", target, "GLenum", attachment, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetFramebufferParameteriv, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL(GLenum, glGetGraphicsResetStatusEXT, (void), (), 0)
-TRACE_GL_VOID(glGetInteger64i_v, (GLenum target, GLuint index, GLint64 * data), (target, index, data), 3, "GLenum", target, "GLuint", index, "GLint64 *", data)
-TRACE_GL_VOID(glGetInteger64v, (GLenum pname, GLint64 * data), (pname, data), 2, "GLenum", pname, "GLint64 *", data)
-TRACE_GL_VOID(glGetInteger64vAPPLE, (GLenum pname, GLint64 * params), (pname, params), 2, "GLenum", pname, "GLint64 *", params)
-TRACE_GL_VOID(glGetIntegeri_v, (GLenum target, GLuint index, GLint * data), (target, index, data), 3, "GLenum", target, "GLuint", index, "GLint *", data)
-TRACE_GL_VOID(glGetIntegeri_vEXT, (GLenum target, GLuint index, GLint * data), (target, index, data), 3, "GLenum", target, "GLuint", index, "GLint *", data)
-TRACE_GL_VOID(glGetIntegerv, (GLenum pname, GLint * data), (pname, data), 2, "GLenum", pname, "GLint *", data)
-TRACE_GL_VOID(glGetInternalformativ, (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint * params), (target, internalformat, pname, bufSize, params), 5, "GLenum", target, "GLenum", internalformat, "GLenum", pname, "GLsizei", bufSize, "GLint *", params)
-TRACE_GL_VOID(glGetLightfv, (GLenum light, GLenum pname, GLfloat * params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetLightxv, (GLenum light, GLenum pname, GLfixed * params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetLightxvOES, (GLenum light, GLenum pname, GLfixed * params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetMaterialfv, (GLenum face, GLenum pname, GLfloat * params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetMaterialxv, (GLenum face, GLenum pname, GLfixed * params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetMaterialxvOES, (GLenum face, GLenum pname, GLfixed * params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetMultisamplefv, (GLenum pname, GLuint index, GLfloat * val), (pname, index, val), 3, "GLenum", pname, "GLuint", index, "GLfloat *", val)
-TRACE_GL_VOID(glGetNextPerfQueryIdINTEL, (GLuint queryId, GLuint * nextQueryId), (queryId, nextQueryId), 2, "GLuint", queryId, "GLuint *", nextQueryId)
-TRACE_GL_VOID(glGetObjectLabelEXT, (GLenum type, GLuint object, GLsizei bufSize, GLsizei * length, GLchar * label), (type, object, bufSize, length, label), 5, "GLenum", type, "GLuint", object, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", label)
-TRACE_GL_VOID(glGetObjectLabelKHR, (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label), (identifier, name, bufSize, length, label), 5, "GLenum", identifier, "GLuint", name, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", label)
-TRACE_GL_VOID(glGetObjectPtrLabelKHR, (const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label), (ptr, bufSize, length, label), 4, "const void *", ptr, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", label)
-TRACE_GL_VOID(glGetPerfCounterInfoINTEL, (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar * counterName, GLuint counterDescLength, GLchar * counterDesc, GLuint * counterOffset, GLuint * counterDataSize, GLuint * counterTypeEnum, GLuint * counterDataTypeEnum, GLuint64 * rawCounterMaxValue), (queryId, counterId, counterNameLength, counterName, counterDescLength, counterDesc, counterOffset, counterDataSize, counterTypeEnum, counterDataTypeEnum, rawCounterMaxValue), 11, "GLuint", queryId, "GLuint", counterId, "GLuint", counterNameLength, "GLchar *", counterName, "GLuint", counterDescLength, "GLchar *", counterDesc, "GLuint *", counterOffset, "GLuint *", counterDataSize, "GLuint *", counterTypeEnum, "GLuint *", counterDataTypeEnum, "GLuint64 *", rawCounterMaxValue)
-TRACE_GL_VOID(glGetPerfMonitorCounterDataAMD, (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint * data, GLint * bytesWritten), (monitor, pname, dataSize, data, bytesWritten), 5, "GLuint", monitor, "GLenum", pname, "GLsizei", dataSize, "GLuint *", data, "GLint *", bytesWritten)
-TRACE_GL_VOID(glGetPerfMonitorCounterInfoAMD, (GLuint group, GLuint counter, GLenum pname, void * data), (group, counter, pname, data), 4, "GLuint", group, "GLuint", counter, "GLenum", pname, "void *", data)
-TRACE_GL_VOID(glGetPerfMonitorCounterStringAMD, (GLuint group, GLuint counter, GLsizei bufSize, GLsizei * length, GLchar * counterString), (group, counter, bufSize, length, counterString), 5, "GLuint", group, "GLuint", counter, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", counterString)
-TRACE_GL_VOID(glGetPerfMonitorCountersAMD, (GLuint group, GLint * numCounters, GLint * maxActiveCounters, GLsizei counterSize, GLuint * counters), (group, numCounters, maxActiveCounters, counterSize, counters), 5, "GLuint", group, "GLint *", numCounters, "GLint *", maxActiveCounters, "GLsizei", counterSize, "GLuint *", counters)
-TRACE_GL_VOID(glGetPerfMonitorGroupStringAMD, (GLuint group, GLsizei bufSize, GLsizei * length, GLchar * groupString), (group, bufSize, length, groupString), 4, "GLuint", group, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", groupString)
-TRACE_GL_VOID(glGetPerfMonitorGroupsAMD, (GLint * numGroups, GLsizei groupsSize, GLuint * groups), (numGroups, groupsSize, groups), 3, "GLint *", numGroups, "GLsizei", groupsSize, "GLuint *", groups)
-TRACE_GL_VOID(glGetPerfQueryDataINTEL, (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid * data, GLuint * bytesWritten), (queryHandle, flags, dataSize, data, bytesWritten), 5, "GLuint", queryHandle, "GLuint", flags, "GLsizei", dataSize, "GLvoid *", data, "GLuint *", bytesWritten)
-TRACE_GL_VOID(glGetPerfQueryIdByNameINTEL, (GLchar * queryName, GLuint * queryId), (queryName, queryId), 2, "GLchar *", queryName, "GLuint *", queryId)
-TRACE_GL_VOID(glGetPerfQueryInfoINTEL, (GLuint queryId, GLuint queryNameLength, GLchar * queryName, GLuint * dataSize, GLuint * noCounters, GLuint * noInstances, GLuint * capsMask), (queryId, queryNameLength, queryName, dataSize, noCounters, noInstances, capsMask), 7, "GLuint", queryId, "GLuint", queryNameLength, "GLchar *", queryName, "GLuint *", dataSize, "GLuint *", noCounters, "GLuint *", noInstances, "GLuint *", capsMask)
-TRACE_GL_VOID(glGetPointerv, (GLenum pname, void ** params), (pname, params), 2, "GLenum", pname, "void **", params)
-TRACE_GL_VOID(glGetPointervKHR, (GLenum pname, void ** params), (pname, params), 2, "GLenum", pname, "void **", params)
-TRACE_GL_VOID(glGetProgramBinary, (GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary), (program, bufSize, length, binaryFormat, binary), 5, "GLuint", program, "GLsizei", bufSize, "GLsizei *", length, "GLenum *", binaryFormat, "void *", binary)
-TRACE_GL_VOID(glGetProgramBinaryOES, (GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary), (program, bufSize, length, binaryFormat, binary), 5, "GLuint", program, "GLsizei", bufSize, "GLsizei *", length, "GLenum *", binaryFormat, "void *", binary)
-TRACE_GL_VOID(glGetProgramInfoLog, (GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog), (program, bufSize, length, infoLog), 4, "GLuint", program, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", infoLog)
-TRACE_GL_VOID(glGetProgramInterfaceiv, (GLuint program, GLenum programInterface, GLenum pname, GLint * params), (program, programInterface, pname, params), 4, "GLuint", program, "GLenum", programInterface, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetProgramPipelineInfoLog, (GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog), (pipeline, bufSize, length, infoLog), 4, "GLuint", pipeline, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", infoLog)
-TRACE_GL_VOID(glGetProgramPipelineInfoLogEXT, (GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog), (pipeline, bufSize, length, infoLog), 4, "GLuint", pipeline, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", infoLog)
-TRACE_GL_VOID(glGetProgramPipelineiv, (GLuint pipeline, GLenum pname, GLint * params), (pipeline, pname, params), 3, "GLuint", pipeline, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetProgramPipelineivEXT, (GLuint pipeline, GLenum pname, GLint * params), (pipeline, pname, params), 3, "GLuint", pipeline, "GLenum", pname, "GLint *", params)
-TRACE_GL(GLuint, glGetProgramResourceIndex, (GLuint program, GLenum programInterface, const GLchar * name), (program, programInterface, name), 3, "GLuint", program, "GLenum", programInterface, "const GLchar *", name)
-TRACE_GL(GLint, glGetProgramResourceLocation, (GLuint program, GLenum programInterface, const GLchar * name), (program, programInterface, name), 3, "GLuint", program, "GLenum", programInterface, "const GLchar *", name)
-TRACE_GL_VOID(glGetProgramResourceName, (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name), (program, programInterface, index, bufSize, length, name), 6, "GLuint", program, "GLenum", programInterface, "GLuint", index, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", name)
-TRACE_GL_VOID(glGetProgramResourceiv, (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei bufSize, GLsizei * length, GLint * params), (program, programInterface, index, propCount, props, bufSize, length, params), 8, "GLuint", program, "GLenum", programInterface, "GLuint", index, "GLsizei", propCount, "const GLenum *", props, "GLsizei", bufSize, "GLsizei *", length, "GLint *", params)
-TRACE_GL_VOID(glGetProgramiv, (GLuint program, GLenum pname, GLint * params), (program, pname, params), 3, "GLuint", program, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetQueryObjecti64vEXT, (GLuint id, GLenum pname, GLint64 * params), (id, pname, params), 3, "GLuint", id, "GLenum", pname, "GLint64 *", params)
-TRACE_GL_VOID(glGetQueryObjectivEXT, (GLuint id, GLenum pname, GLint * params), (id, pname, params), 3, "GLuint", id, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetQueryObjectui64vEXT, (GLuint id, GLenum pname, GLuint64 * params), (id, pname, params), 3, "GLuint", id, "GLenum", pname, "GLuint64 *", params)
-TRACE_GL_VOID(glGetQueryObjectuiv, (GLuint id, GLenum pname, GLuint * params), (id, pname, params), 3, "GLuint", id, "GLenum", pname, "GLuint *", params)
-TRACE_GL_VOID(glGetQueryObjectuivEXT, (GLuint id, GLenum pname, GLuint * params), (id, pname, params), 3, "GLuint", id, "GLenum", pname, "GLuint *", params)
-TRACE_GL_VOID(glGetQueryiv, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetQueryivEXT, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetRenderbufferParameteriv, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetRenderbufferParameterivOES, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetSamplerParameterIivEXT, (GLuint sampler, GLenum pname, GLint * params), (sampler, pname, params), 3, "GLuint", sampler, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetSamplerParameterIuivEXT, (GLuint sampler, GLenum pname, GLuint * params), (sampler, pname, params), 3, "GLuint", sampler, "GLenum", pname, "GLuint *", params)
-TRACE_GL_VOID(glGetSamplerParameterfv, (GLuint sampler, GLenum pname, GLfloat * params), (sampler, pname, params), 3, "GLuint", sampler, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetSamplerParameteriv, (GLuint sampler, GLenum pname, GLint * params), (sampler, pname, params), 3, "GLuint", sampler, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetShaderInfoLog, (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog), (shader, bufSize, length, infoLog), 4, "GLuint", shader, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", infoLog)
-TRACE_GL_VOID(glGetShaderPrecisionFormat, (GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision), (shadertype, precisiontype, range, precision), 4, "GLenum", shadertype, "GLenum", precisiontype, "GLint *", range, "GLint *", precision)
-TRACE_GL_VOID(glGetShaderSource, (GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source), (shader, bufSize, length, source), 4, "GLuint", shader, "GLsizei", bufSize, "GLsizei *", length, "GLchar *", source)
-TRACE_GL_VOID(glGetShaderiv, (GLuint shader, GLenum pname, GLint * params), (shader, pname, params), 3, "GLuint", shader, "GLenum", pname, "GLint *", params)
-TRACE_GL(const GLubyte *, glGetString, (GLenum name), (name), 1, "GLenum", name)
-TRACE_GL(const GLubyte *, glGetStringi, (GLenum name, GLuint index), (name, index), 2, "GLenum", name, "GLuint", index)
-TRACE_GL_VOID(glGetSynciv, (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values), (sync, pname, bufSize, length, values), 5, "GLsync", sync, "GLenum", pname, "GLsizei", bufSize, "GLsizei *", length, "GLint *", values)
-TRACE_GL_VOID(glGetSyncivAPPLE, (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values), (sync, pname, bufSize, length, values), 5, "GLsync", sync, "GLenum", pname, "GLsizei", bufSize, "GLsizei *", length, "GLint *", values)
-TRACE_GL_VOID(glGetTexEnvfv, (GLenum target, GLenum pname, GLfloat * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetTexEnviv, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetTexEnvxv, (GLenum target, GLenum pname, GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetTexEnvxvOES, (GLenum target, GLenum pname, GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetTexGenfvOES, (GLenum coord, GLenum pname, GLfloat * params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetTexGenivOES, (GLenum coord, GLenum pname, GLint * params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetTexGenxvOES, (GLenum coord, GLenum pname, GLfixed * params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetTexLevelParameterfv, (GLenum target, GLint level, GLenum pname, GLfloat * params), (target, level, pname, params), 4, "GLenum", target, "GLint", level, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetTexLevelParameteriv, (GLenum target, GLint level, GLenum pname, GLint * params), (target, level, pname, params), 4, "GLenum", target, "GLint", level, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetTexParameterIivEXT, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetTexParameterIuivEXT, (GLenum target, GLenum pname, GLuint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLuint *", params)
-TRACE_GL_VOID(glGetTexParameterfv, (GLenum target, GLenum pname, GLfloat * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetTexParameteriv, (GLenum target, GLenum pname, GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetTexParameterxv, (GLenum target, GLenum pname, GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetTexParameterxvOES, (GLenum target, GLenum pname, GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "GLfixed *", params)
-TRACE_GL_VOID(glGetTransformFeedbackVarying, (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name), (program, index, bufSize, length, size, type, name), 7, "GLuint", program, "GLuint", index, "GLsizei", bufSize, "GLsizei *", length, "GLsizei *", size, "GLenum *", type, "GLchar *", name)
-TRACE_GL_VOID(glGetTranslatedShaderSourceANGLE, (GLuint shader, GLsizei bufsize, GLsizei * length, GLchar * source), (shader, bufsize, length, source), 4, "GLuint", shader, "GLsizei", bufsize, "GLsizei *", length, "GLchar *", source)
-TRACE_GL(GLuint, glGetUniformBlockIndex, (GLuint program, const GLchar * uniformBlockName), (program, uniformBlockName), 2, "GLuint", program, "const GLchar *", uniformBlockName)
-TRACE_GL_VOID(glGetUniformIndices, (GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices), (program, uniformCount, uniformNames, uniformIndices), 4, "GLuint", program, "GLsizei", uniformCount, "const GLchar *const*", uniformNames, "GLuint *", uniformIndices)
-TRACE_GL(GLint, glGetUniformLocation, (GLuint program, const GLchar * name), (program, name), 2, "GLuint", program, "const GLchar *", name)
-TRACE_GL_VOID(glGetUniformfv, (GLuint program, GLint location, GLfloat * params), (program, location, params), 3, "GLuint", program, "GLint", location, "GLfloat *", params)
-TRACE_GL_VOID(glGetUniformiv, (GLuint program, GLint location, GLint * params), (program, location, params), 3, "GLuint", program, "GLint", location, "GLint *", params)
-TRACE_GL_VOID(glGetUniformuiv, (GLuint program, GLint location, GLuint * params), (program, location, params), 3, "GLuint", program, "GLint", location, "GLuint *", params)
-TRACE_GL_VOID(glGetVertexAttribIiv, (GLuint index, GLenum pname, GLint * params), (index, pname, params), 3, "GLuint", index, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetVertexAttribIuiv, (GLuint index, GLenum pname, GLuint * params), (index, pname, params), 3, "GLuint", index, "GLenum", pname, "GLuint *", params)
-TRACE_GL_VOID(glGetVertexAttribPointerv, (GLuint index, GLenum pname, void ** pointer), (index, pname, pointer), 3, "GLuint", index, "GLenum", pname, "void **", pointer)
-TRACE_GL_VOID(glGetVertexAttribfv, (GLuint index, GLenum pname, GLfloat * params), (index, pname, params), 3, "GLuint", index, "GLenum", pname, "GLfloat *", params)
-TRACE_GL_VOID(glGetVertexAttribiv, (GLuint index, GLenum pname, GLint * params), (index, pname, params), 3, "GLuint", index, "GLenum", pname, "GLint *", params)
-TRACE_GL_VOID(glGetnUniformfvEXT, (GLuint program, GLint location, GLsizei bufSize, GLfloat * params), (program, location, bufSize, params), 4, "GLuint", program, "GLint", location, "GLsizei", bufSize, "GLfloat *", params)
-TRACE_GL_VOID(glGetnUniformivEXT, (GLuint program, GLint location, GLsizei bufSize, GLint * params), (program, location, bufSize, params), 4, "GLuint", program, "GLint", location, "GLsizei", bufSize, "GLint *", params)
-TRACE_GL_VOID(glHint, (GLenum target, GLenum mode), (target, mode), 2, "GLenum", target, "GLenum", mode)
-TRACE_GL_VOID(glInsertEventMarkerEXT, (GLsizei length, const GLchar * marker), (length, marker), 2, "GLsizei", length, "const GLchar *", marker)
-TRACE_GL_VOID(glInvalidateFramebuffer, (GLenum target, GLsizei numAttachments, const GLenum * attachments), (target, numAttachments, attachments), 3, "GLenum", target, "GLsizei", numAttachments, "const GLenum *", attachments)
-TRACE_GL_VOID(glInvalidateSubFramebuffer, (GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height), (target, numAttachments, attachments, x, y, width, height), 7, "GLenum", target, "GLsizei", numAttachments, "const GLenum *", attachments, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
-TRACE_GL(GLboolean, glIsBuffer, (GLuint buffer), (buffer), 1, "GLuint", buffer)
-TRACE_GL(GLboolean, glIsEnabled, (GLenum cap), (cap), 1, "GLenum", cap)
-TRACE_GL(GLboolean, glIsEnablediEXT, (GLenum target, GLuint index), (target, index), 2, "GLenum", target, "GLuint", index)
-TRACE_GL(GLboolean, glIsFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
-TRACE_GL(GLboolean, glIsFramebuffer, (GLuint framebuffer), (framebuffer), 1, "GLuint", framebuffer)
-TRACE_GL(GLboolean, glIsFramebufferOES, (GLuint framebuffer), (framebuffer), 1, "GLuint", framebuffer)
-TRACE_GL(GLboolean, glIsProgram, (GLuint program), (program), 1, "GLuint", program)
-TRACE_GL(GLboolean, glIsProgramPipeline, (GLuint pipeline), (pipeline), 1, "GLuint", pipeline)
-TRACE_GL(GLboolean, glIsProgramPipelineEXT, (GLuint pipeline), (pipeline), 1, "GLuint", pipeline)
-TRACE_GL(GLboolean, glIsQuery, (GLuint id), (id), 1, "GLuint", id)
-TRACE_GL(GLboolean, glIsQueryEXT, (GLuint id), (id), 1, "GLuint", id)
-TRACE_GL(GLboolean, glIsRenderbuffer, (GLuint renderbuffer), (renderbuffer), 1, "GLuint", renderbuffer)
-TRACE_GL(GLboolean, glIsRenderbufferOES, (GLuint renderbuffer), (renderbuffer), 1, "GLuint", renderbuffer)
-TRACE_GL(GLboolean, glIsSampler, (GLuint sampler), (sampler), 1, "GLuint", sampler)
-TRACE_GL(GLboolean, glIsShader, (GLuint shader), (shader), 1, "GLuint", shader)
-TRACE_GL(GLboolean, glIsSync, (GLsync sync), (sync), 1, "GLsync", sync)
-TRACE_GL(GLboolean, glIsSyncAPPLE, (GLsync sync), (sync), 1, "GLsync", sync)
-TRACE_GL(GLboolean, glIsTexture, (GLuint texture), (texture), 1, "GLuint", texture)
-TRACE_GL(GLboolean, glIsTransformFeedback, (GLuint id), (id), 1, "GLuint", id)
-TRACE_GL(GLboolean, glIsVertexArray, (GLuint array), (array), 1, "GLuint", array)
-TRACE_GL(GLboolean, glIsVertexArrayOES, (GLuint array), (array), 1, "GLuint", array)
-TRACE_GL_VOID(glLabelObjectEXT, (GLenum type, GLuint object, GLsizei length, const GLchar * label), (type, object, length, label), 4, "GLenum", type, "GLuint", object, "GLsizei", length, "const GLchar *", label)
-TRACE_GL_VOID(glLightModelf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glLightModelfv, (GLenum pname, const GLfloat * params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glLightModelx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glLightModelxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glLightModelxv, (GLenum pname, const GLfixed * param), (pname, param), 2, "GLenum", pname, "const GLfixed *", param)
-TRACE_GL_VOID(glLightModelxvOES, (GLenum pname, const GLfixed * param), (pname, param), 2, "GLenum", pname, "const GLfixed *", param)
-TRACE_GL_VOID(glLightf, (GLenum light, GLenum pname, GLfloat param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glLightfv, (GLenum light, GLenum pname, const GLfloat * params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glLightx, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glLightxOES, (GLenum light, GLenum pname, GLfixed param), (light, pname, param), 3, "GLenum", light, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glLightxv, (GLenum light, GLenum pname, const GLfixed * params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glLightxvOES, (GLenum light, GLenum pname, const GLfixed * params), (light, pname, params), 3, "GLenum", light, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glLineWidth, (GLfloat width), (width), 1, "GLfloat", width)
-TRACE_GL_VOID(glLineWidthx, (GLfixed width), (width), 1, "GLfixed", width)
-TRACE_GL_VOID(glLineWidthxOES, (GLfixed width), (width), 1, "GLfixed", width)
-TRACE_GL_VOID(glLinkProgram, (GLuint program), (program), 1, "GLuint", program)
-TRACE_GL_VOID(glLoadIdentity, (void), (), 0)
-TRACE_GL_VOID(glLoadMatrixf, (const GLfloat * m), (m), 1, "const GLfloat *", m)
-TRACE_GL_VOID(glLoadMatrixx, (const GLfixed * m), (m), 1, "const GLfixed *", m)
-TRACE_GL_VOID(glLoadMatrixxOES, (const GLfixed * m), (m), 1, "const GLfixed *", m)
-TRACE_GL_VOID(glLoadPaletteFromModelViewMatrixOES, (void), (), 0)
-TRACE_GL_VOID(glLogicOp, (GLenum opcode), (opcode), 1, "GLenum", opcode)
-TRACE_GL(void *, glMapBufferOES, (GLenum target, GLenum access), (target, access), 2, "GLenum", target, "GLenum", access)
-TRACE_GL(void *, glMapBufferRange, (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access), (target, offset, length, access), 4, "GLenum", target, "GLintptr", offset, "GLsizeiptr", length, "GLbitfield", access)
-TRACE_GL(void *, glMapBufferRangeEXT, (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access), (target, offset, length, access), 4, "GLenum", target, "GLintptr", offset, "GLsizeiptr", length, "GLbitfield", access)
-TRACE_GL_VOID(glMaterialf, (GLenum face, GLenum pname, GLfloat param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glMaterialfv, (GLenum face, GLenum pname, const GLfloat * params), (face, pname, params), 3, "GLenum", face, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glMaterialx, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glMaterialxOES, (GLenum face, GLenum pname, GLfixed param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glMaterialxv, (GLenum face, GLenum pname, const GLfixed * param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", param)
-TRACE_GL_VOID(glMaterialxvOES, (GLenum face, GLenum pname, const GLfixed * param), (face, pname, param), 3, "GLenum", face, "GLenum", pname, "const GLfixed *", param)
-TRACE_GL_VOID(glMatrixIndexPointerOES, (GLint size, GLenum type, GLsizei stride, const void * pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glMatrixMode, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glMemoryBarrier, (GLbitfield barriers), (barriers), 1, "GLbitfield", barriers)
-TRACE_GL_VOID(glMemoryBarrierByRegion, (GLbitfield barriers), (barriers), 1, "GLbitfield", barriers)
-TRACE_GL_VOID(glMinSampleShadingOES, (GLfloat value), (value), 1, "GLfloat", value)
-TRACE_GL_VOID(glMultMatrixf, (const GLfloat * m), (m), 1, "const GLfloat *", m)
-TRACE_GL_VOID(glMultMatrixx, (const GLfixed * m), (m), 1, "const GLfixed *", m)
-TRACE_GL_VOID(glMultMatrixxOES, (const GLfixed * m), (m), 1, "const GLfixed *", m)
-TRACE_GL_VOID(glMultiDrawArraysEXT, (GLenum mode, const GLint * first, const GLsizei * count, GLsizei primcount), (mode, first, count, primcount), 4, "GLenum", mode, "const GLint *", first, "const GLsizei *", count, "GLsizei", primcount)
-TRACE_GL_VOID(glMultiDrawElementsEXT, (GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei primcount), (mode, count, type, indices, primcount), 5, "GLenum", mode, "const GLsizei *", count, "GLenum", type, "const void *const*", indices, "GLsizei", primcount)
-TRACE_GL_VOID(glMultiTexCoord1bOES, (GLenum texture, GLbyte s), (texture, s), 2, "GLenum", texture, "GLbyte", s)
-TRACE_GL_VOID(glMultiTexCoord1bvOES, (GLenum texture, const GLbyte * coords), (texture, coords), 2, "GLenum", texture, "const GLbyte *", coords)
-TRACE_GL_VOID(glMultiTexCoord2bOES, (GLenum texture, GLbyte s, GLbyte t), (texture, s, t), 3, "GLenum", texture, "GLbyte", s, "GLbyte", t)
-TRACE_GL_VOID(glMultiTexCoord2bvOES, (GLenum texture, const GLbyte * coords), (texture, coords), 2, "GLenum", texture, "const GLbyte *", coords)
-TRACE_GL_VOID(glMultiTexCoord3bOES, (GLenum texture, GLbyte s, GLbyte t, GLbyte r), (texture, s, t, r), 4, "GLenum", texture, "GLbyte", s, "GLbyte", t, "GLbyte", r)
-TRACE_GL_VOID(glMultiTexCoord3bvOES, (GLenum texture, const GLbyte * coords), (texture, coords), 2, "GLenum", texture, "const GLbyte *", coords)
-TRACE_GL_VOID(glMultiTexCoord4bOES, (GLenum texture, GLbyte s, GLbyte t, GLbyte r, GLbyte q), (texture, s, t, r, q), 5, "GLenum", texture, "GLbyte", s, "GLbyte", t, "GLbyte", r, "GLbyte", q)
-TRACE_GL_VOID(glMultiTexCoord4bvOES, (GLenum texture, const GLbyte * coords), (texture, coords), 2, "GLenum", texture, "const GLbyte *", coords)
-TRACE_GL_VOID(glMultiTexCoord4f, (GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q), (target, s, t, r, q), 5, "GLenum", target, "GLfloat", s, "GLfloat", t, "GLfloat", r, "GLfloat", q)
-TRACE_GL_VOID(glMultiTexCoord4x, (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (texture, s, t, r, q), 5, "GLenum", texture, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
-TRACE_GL_VOID(glMultiTexCoord4xOES, (GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q), (texture, s, t, r, q), 5, "GLenum", texture, "GLfixed", s, "GLfixed", t, "GLfixed", r, "GLfixed", q)
-TRACE_GL_VOID(glNormal3f, (GLfloat nx, GLfloat ny, GLfloat nz), (nx, ny, nz), 3, "GLfloat", nx, "GLfloat", ny, "GLfloat", nz)
-TRACE_GL_VOID(glNormal3x, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
-TRACE_GL_VOID(glNormal3xOES, (GLfixed nx, GLfixed ny, GLfixed nz), (nx, ny, nz), 3, "GLfixed", nx, "GLfixed", ny, "GLfixed", nz)
-TRACE_GL_VOID(glNormalPointer, (GLenum type, GLsizei stride, const void * pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glObjectLabelKHR, (GLenum identifier, GLuint name, GLsizei length, const GLchar * label), (identifier, name, length, label), 4, "GLenum", identifier, "GLuint", name, "GLsizei", length, "const GLchar *", label)
-TRACE_GL_VOID(glObjectPtrLabelKHR, (const void * ptr, GLsizei length, const GLchar * label), (ptr, length, label), 3, "const void *", ptr, "GLsizei", length, "const GLchar *", label)
-TRACE_GL_VOID(glOrthof, (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f), (l, r, b, t, n, f), 6, "GLfloat", l, "GLfloat", r, "GLfloat", b, "GLfloat", t, "GLfloat", n, "GLfloat", f)
-TRACE_GL_VOID(glOrthofOES, (GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f), (l, r, b, t, n, f), 6, "GLfloat", l, "GLfloat", r, "GLfloat", b, "GLfloat", t, "GLfloat", n, "GLfloat", f)
-TRACE_GL_VOID(glOrthox, (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f), (l, r, b, t, n, f), 6, "GLfixed", l, "GLfixed", r, "GLfixed", b, "GLfixed", t, "GLfixed", n, "GLfixed", f)
-TRACE_GL_VOID(glOrthoxOES, (GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f), (l, r, b, t, n, f), 6, "GLfixed", l, "GLfixed", r, "GLfixed", b, "GLfixed", t, "GLfixed", n, "GLfixed", f)
-TRACE_GL_VOID(glPatchParameteriEXT, (GLenum pname, GLint value), (pname, value), 2, "GLenum", pname, "GLint", value)
-TRACE_GL_VOID(glPauseTransformFeedback, (void), (), 0)
-TRACE_GL_VOID(glPixelStorei, (GLenum pname, GLint param), (pname, param), 2, "GLenum", pname, "GLint", param)
-TRACE_GL_VOID(glPointParameterf, (GLenum pname, GLfloat param), (pname, param), 2, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glPointParameterfv, (GLenum pname, const GLfloat * params), (pname, params), 2, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glPointParameterx, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glPointParameterxOES, (GLenum pname, GLfixed param), (pname, param), 2, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glPointParameterxv, (GLenum pname, const GLfixed * params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glPointParameterxvOES, (GLenum pname, const GLfixed * params), (pname, params), 2, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glPointSize, (GLfloat size), (size), 1, "GLfloat", size)
-TRACE_GL_VOID(glPointSizePointerOES, (GLenum type, GLsizei stride, const void * pointer), (type, stride, pointer), 3, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glPointSizex, (GLfixed size), (size), 1, "GLfixed", size)
-TRACE_GL_VOID(glPointSizexOES, (GLfixed size), (size), 1, "GLfixed", size)
-TRACE_GL_VOID(glPolygonOffset, (GLfloat factor, GLfloat units), (factor, units), 2, "GLfloat", factor, "GLfloat", units)
-TRACE_GL_VOID(glPolygonOffsetx, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
-TRACE_GL_VOID(glPolygonOffsetxOES, (GLfixed factor, GLfixed units), (factor, units), 2, "GLfixed", factor, "GLfixed", units)
-TRACE_GL_VOID(glPopDebugGroupKHR, (void), (), 0)
-TRACE_GL_VOID(glPopGroupMarkerEXT, (void), (), 0)
-TRACE_GL_VOID(glPopMatrix, (void), (), 0)
-TRACE_GL_VOID(glPrimitiveBoundingBoxEXT, (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW), (minX, minY, minZ, minW, maxX, maxY, maxZ, maxW), 8, "GLfloat", minX, "GLfloat", minY, "GLfloat", minZ, "GLfloat", minW, "GLfloat", maxX, "GLfloat", maxY, "GLfloat", maxZ, "GLfloat", maxW)
-TRACE_GL_VOID(glProgramBinary, (GLuint program, GLenum binaryFormat, const void * binary, GLsizei length), (program, binaryFormat, binary, length), 4, "GLuint", program, "GLenum", binaryFormat, "const void *", binary, "GLsizei", length)
-TRACE_GL_VOID(glProgramBinaryOES, (GLuint program, GLenum binaryFormat, const void * binary, GLint length), (program, binaryFormat, binary, length), 4, "GLuint", program, "GLenum", binaryFormat, "const void *", binary, "GLint", length)
-TRACE_GL_VOID(glProgramParameteri, (GLuint program, GLenum pname, GLint value), (program, pname, value), 3, "GLuint", program, "GLenum", pname, "GLint", value)
-TRACE_GL_VOID(glProgramParameteriEXT, (GLuint program, GLenum pname, GLint value), (program, pname, value), 3, "GLuint", program, "GLenum", pname, "GLint", value)
-TRACE_GL_VOID(glProgramUniform1f, (GLuint program, GLint location, GLfloat v0), (program, location, v0), 3, "GLuint", program, "GLint", location, "GLfloat", v0)
-TRACE_GL_VOID(glProgramUniform1fEXT, (GLuint program, GLint location, GLfloat v0), (program, location, v0), 3, "GLuint", program, "GLint", location, "GLfloat", v0)
-TRACE_GL_VOID(glProgramUniform1fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform1fvEXT, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform1i, (GLuint program, GLint location, GLint v0), (program, location, v0), 3, "GLuint", program, "GLint", location, "GLint", v0)
-TRACE_GL_VOID(glProgramUniform1iEXT, (GLuint program, GLint location, GLint v0), (program, location, v0), 3, "GLuint", program, "GLint", location, "GLint", v0)
-TRACE_GL_VOID(glProgramUniform1iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform1ivEXT, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform1ui, (GLuint program, GLint location, GLuint v0), (program, location, v0), 3, "GLuint", program, "GLint", location, "GLuint", v0)
-TRACE_GL_VOID(glProgramUniform1uiEXT, (GLuint program, GLint location, GLuint v0), (program, location, v0), 3, "GLuint", program, "GLint", location, "GLuint", v0)
-TRACE_GL_VOID(glProgramUniform1uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform1uivEXT, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform2f, (GLuint program, GLint location, GLfloat v0, GLfloat v1), (program, location, v0, v1), 4, "GLuint", program, "GLint", location, "GLfloat", v0, "GLfloat", v1)
-TRACE_GL_VOID(glProgramUniform2fEXT, (GLuint program, GLint location, GLfloat v0, GLfloat v1), (program, location, v0, v1), 4, "GLuint", program, "GLint", location, "GLfloat", v0, "GLfloat", v1)
-TRACE_GL_VOID(glProgramUniform2fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform2fvEXT, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform2i, (GLuint program, GLint location, GLint v0, GLint v1), (program, location, v0, v1), 4, "GLuint", program, "GLint", location, "GLint", v0, "GLint", v1)
-TRACE_GL_VOID(glProgramUniform2iEXT, (GLuint program, GLint location, GLint v0, GLint v1), (program, location, v0, v1), 4, "GLuint", program, "GLint", location, "GLint", v0, "GLint", v1)
-TRACE_GL_VOID(glProgramUniform2iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform2ivEXT, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform2ui, (GLuint program, GLint location, GLuint v0, GLuint v1), (program, location, v0, v1), 4, "GLuint", program, "GLint", location, "GLuint", v0, "GLuint", v1)
-TRACE_GL_VOID(glProgramUniform2uiEXT, (GLuint program, GLint location, GLuint v0, GLuint v1), (program, location, v0, v1), 4, "GLuint", program, "GLint", location, "GLuint", v0, "GLuint", v1)
-TRACE_GL_VOID(glProgramUniform2uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform2uivEXT, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform3f, (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2), (program, location, v0, v1, v2), 5, "GLuint", program, "GLint", location, "GLfloat", v0, "GLfloat", v1, "GLfloat", v2)
-TRACE_GL_VOID(glProgramUniform3fEXT, (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2), (program, location, v0, v1, v2), 5, "GLuint", program, "GLint", location, "GLfloat", v0, "GLfloat", v1, "GLfloat", v2)
-TRACE_GL_VOID(glProgramUniform3fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform3fvEXT, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform3i, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2), (program, location, v0, v1, v2), 5, "GLuint", program, "GLint", location, "GLint", v0, "GLint", v1, "GLint", v2)
-TRACE_GL_VOID(glProgramUniform3iEXT, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2), (program, location, v0, v1, v2), 5, "GLuint", program, "GLint", location, "GLint", v0, "GLint", v1, "GLint", v2)
-TRACE_GL_VOID(glProgramUniform3iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform3ivEXT, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform3ui, (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2), (program, location, v0, v1, v2), 5, "GLuint", program, "GLint", location, "GLuint", v0, "GLuint", v1, "GLuint", v2)
-TRACE_GL_VOID(glProgramUniform3uiEXT, (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2), (program, location, v0, v1, v2), 5, "GLuint", program, "GLint", location, "GLuint", v0, "GLuint", v1, "GLuint", v2)
-TRACE_GL_VOID(glProgramUniform3uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform3uivEXT, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform4f, (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3), (program, location, v0, v1, v2, v3), 6, "GLuint", program, "GLint", location, "GLfloat", v0, "GLfloat", v1, "GLfloat", v2, "GLfloat", v3)
-TRACE_GL_VOID(glProgramUniform4fEXT, (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3), (program, location, v0, v1, v2, v3), 6, "GLuint", program, "GLint", location, "GLfloat", v0, "GLfloat", v1, "GLfloat", v2, "GLfloat", v3)
-TRACE_GL_VOID(glProgramUniform4fv, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform4fvEXT, (GLuint program, GLint location, GLsizei count, const GLfloat * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniform4i, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3), (program, location, v0, v1, v2, v3), 6, "GLuint", program, "GLint", location, "GLint", v0, "GLint", v1, "GLint", v2, "GLint", v3)
-TRACE_GL_VOID(glProgramUniform4iEXT, (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3), (program, location, v0, v1, v2, v3), 6, "GLuint", program, "GLint", location, "GLint", v0, "GLint", v1, "GLint", v2, "GLint", v3)
-TRACE_GL_VOID(glProgramUniform4iv, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform4ivEXT, (GLuint program, GLint location, GLsizei count, const GLint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glProgramUniform4ui, (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3), (program, location, v0, v1, v2, v3), 6, "GLuint", program, "GLint", location, "GLuint", v0, "GLuint", v1, "GLuint", v2, "GLuint", v3)
-TRACE_GL_VOID(glProgramUniform4uiEXT, (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3), (program, location, v0, v1, v2, v3), 6, "GLuint", program, "GLint", location, "GLuint", v0, "GLuint", v1, "GLuint", v2, "GLuint", v3)
-TRACE_GL_VOID(glProgramUniform4uiv, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniform4uivEXT, (GLuint program, GLint location, GLsizei count, const GLuint * value), (program, location, count, value), 4, "GLuint", program, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glProgramUniformMatrix2fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix2fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix2x3fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix2x3fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix2x4fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix2x4fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix3fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix3fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix3x2fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix3x2fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix3x4fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix3x4fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix4fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix4fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix4x2fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix4x2fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix4x3fv, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glProgramUniformMatrix4x3fvEXT, (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (program, location, count, transpose, value), 5, "GLuint", program, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glPushDebugGroupKHR, (GLenum source, GLuint id, GLsizei length, const GLchar * message), (source, id, length, message), 4, "GLenum", source, "GLuint", id, "GLsizei", length, "const GLchar *", message)
-TRACE_GL_VOID(glPushGroupMarkerEXT, (GLsizei length, const GLchar * marker), (length, marker), 2, "GLsizei", length, "const GLchar *", marker)
-TRACE_GL_VOID(glPushMatrix, (void), (), 0)
-TRACE_GL_VOID(glQueryCounterEXT, (GLuint id, GLenum target), (id, target), 2, "GLuint", id, "GLenum", target)
-TRACE_GL(GLbitfield, glQueryMatrixxOES, (GLfixed * mantissa, GLint * exponent), (mantissa, exponent), 2, "GLfixed *", mantissa, "GLint *", exponent)
-TRACE_GL_VOID(glReadBuffer, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glReadBufferIndexedEXT, (GLenum src, GLint index), (src, index), 2, "GLenum", src, "GLint", index)
-TRACE_GL_VOID(glReadBufferNV, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glReadPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels), (x, y, width, height, format, type, pixels), 7, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLenum", type, "void *", pixels)
-TRACE_GL_VOID(glReadnPixelsEXT, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data), (x, y, width, height, format, type, bufSize, data), 8, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLenum", type, "GLsizei", bufSize, "void *", data)
-TRACE_GL_VOID(glReleaseShaderCompiler, (void), (), 0)
-TRACE_GL_VOID(glRenderbufferStorage, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height), (target, internalformat, width, height), 4, "GLenum", target, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageMultisample, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageMultisampleANGLE, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageMultisampleAPPLE, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageMultisampleEXT, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageMultisampleIMG, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageMultisampleNV, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height), 5, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glRenderbufferStorageOES, (GLenum target, GLenum internalformat, GLsizei width, GLsizei height), (target, internalformat, width, height), 4, "GLenum", target, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glResolveMultisampleFramebufferAPPLE, (void), (), 0)
-TRACE_GL_VOID(glResumeTransformFeedback, (void), (), 0)
-TRACE_GL_VOID(glRotatef, (GLfloat angle, GLfloat x, GLfloat y, GLfloat z), (angle, x, y, z), 4, "GLfloat", angle, "GLfloat", x, "GLfloat", y, "GLfloat", z)
-TRACE_GL_VOID(glRotatex, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
-TRACE_GL_VOID(glRotatexOES, (GLfixed angle, GLfixed x, GLfixed y, GLfixed z), (angle, x, y, z), 4, "GLfixed", angle, "GLfixed", x, "GLfixed", y, "GLfixed", z)
-TRACE_GL_VOID(glSampleCoverage, (GLfloat value, GLboolean invert), (value, invert), 2, "GLfloat", value, "GLboolean", invert)
-TRACE_GL_VOID(glSampleCoverageOES, (GLfixed value, GLboolean invert), (value, invert), 2, "GLfixed", value, "GLboolean", invert)
-TRACE_GL_VOID(glSampleCoveragex, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
-TRACE_GL_VOID(glSampleCoveragexOES, (GLclampx value, GLboolean invert), (value, invert), 2, "GLclampx", value, "GLboolean", invert)
-TRACE_GL_VOID(glSampleMaski, (GLuint maskNumber, GLbitfield mask), (maskNumber, mask), 2, "GLuint", maskNumber, "GLbitfield", mask)
-TRACE_GL_VOID(glSamplerParameterIivEXT, (GLuint sampler, GLenum pname, const GLint * param), (sampler, pname, param), 3, "GLuint", sampler, "GLenum", pname, "const GLint *", param)
-TRACE_GL_VOID(glSamplerParameterIuivEXT, (GLuint sampler, GLenum pname, const GLuint * param), (sampler, pname, param), 3, "GLuint", sampler, "GLenum", pname, "const GLuint *", param)
-TRACE_GL_VOID(glSamplerParameterf, (GLuint sampler, GLenum pname, GLfloat param), (sampler, pname, param), 3, "GLuint", sampler, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glSamplerParameterfv, (GLuint sampler, GLenum pname, const GLfloat * param), (sampler, pname, param), 3, "GLuint", sampler, "GLenum", pname, "const GLfloat *", param)
-TRACE_GL_VOID(glSamplerParameteri, (GLuint sampler, GLenum pname, GLint param), (sampler, pname, param), 3, "GLuint", sampler, "GLenum", pname, "GLint", param)
-TRACE_GL_VOID(glSamplerParameteriv, (GLuint sampler, GLenum pname, const GLint * param), (sampler, pname, param), 3, "GLuint", sampler, "GLenum", pname, "const GLint *", param)
-TRACE_GL_VOID(glScalef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
-TRACE_GL_VOID(glScalex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
-TRACE_GL_VOID(glScalexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
-TRACE_GL_VOID(glScissor, (GLint x, GLint y, GLsizei width, GLsizei height), (x, y, width, height), 4, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glSelectPerfMonitorCountersAMD, (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint * counterList), (monitor, enable, group, numCounters, counterList), 5, "GLuint", monitor, "GLboolean", enable, "GLuint", group, "GLint", numCounters, "GLuint *", counterList)
-TRACE_GL_VOID(glSetFenceNV, (GLuint fence, GLenum condition), (fence, condition), 2, "GLuint", fence, "GLenum", condition)
-TRACE_GL_VOID(glShadeModel, (GLenum mode), (mode), 1, "GLenum", mode)
-TRACE_GL_VOID(glShaderBinary, (GLsizei count, const GLuint * shaders, GLenum binaryformat, const void * binary, GLsizei length), (count, shaders, binaryformat, binary, length), 5, "GLsizei", count, "const GLuint *", shaders, "GLenum", binaryformat, "const void *", binary, "GLsizei", length)
-TRACE_GL_VOID(glShaderSource, (GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length), (shader, count, string, length), 4, "GLuint", shader, "GLsizei", count, "const GLchar *const*", string, "const GLint *", length)
-TRACE_GL_VOID(glStartTilingQCOM, (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask), (x, y, width, height, preserveMask), 5, "GLuint", x, "GLuint", y, "GLuint", width, "GLuint", height, "GLbitfield", preserveMask)
-TRACE_GL_VOID(glStencilFunc, (GLenum func, GLint ref, GLuint mask), (func, ref, mask), 3, "GLenum", func, "GLint", ref, "GLuint", mask)
-TRACE_GL_VOID(glStencilFuncSeparate, (GLenum face, GLenum func, GLint ref, GLuint mask), (face, func, ref, mask), 4, "GLenum", face, "GLenum", func, "GLint", ref, "GLuint", mask)
-TRACE_GL_VOID(glStencilMask, (GLuint mask), (mask), 1, "GLuint", mask)
-TRACE_GL_VOID(glStencilMaskSeparate, (GLenum face, GLuint mask), (face, mask), 2, "GLenum", face, "GLuint", mask)
-TRACE_GL_VOID(glStencilOp, (GLenum fail, GLenum zfail, GLenum zpass), (fail, zfail, zpass), 3, "GLenum", fail, "GLenum", zfail, "GLenum", zpass)
-TRACE_GL_VOID(glStencilOpSeparate, (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass), (face, sfail, dpfail, dppass), 4, "GLenum", face, "GLenum", sfail, "GLenum", dpfail, "GLenum", dppass)
-TRACE_GL(GLboolean, glTestFenceNV, (GLuint fence), (fence), 1, "GLuint", fence)
-TRACE_GL_VOID(glTexBufferEXT, (GLenum target, GLenum internalformat, GLuint buffer), (target, internalformat, buffer), 3, "GLenum", target, "GLenum", internalformat, "GLuint", buffer)
-TRACE_GL_VOID(glTexBufferRangeEXT, (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size), (target, internalformat, buffer, offset, size), 5, "GLenum", target, "GLenum", internalformat, "GLuint", buffer, "GLintptr", offset, "GLsizeiptr", size)
-TRACE_GL_VOID(glTexCoord1bOES, (GLbyte s), (s), 1, "GLbyte", s)
-TRACE_GL_VOID(glTexCoord1bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glTexCoord2bOES, (GLbyte s, GLbyte t), (s, t), 2, "GLbyte", s, "GLbyte", t)
-TRACE_GL_VOID(glTexCoord2bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glTexCoord3bOES, (GLbyte s, GLbyte t, GLbyte r), (s, t, r), 3, "GLbyte", s, "GLbyte", t, "GLbyte", r)
-TRACE_GL_VOID(glTexCoord3bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glTexCoord4bOES, (GLbyte s, GLbyte t, GLbyte r, GLbyte q), (s, t, r, q), 4, "GLbyte", s, "GLbyte", t, "GLbyte", r, "GLbyte", q)
-TRACE_GL_VOID(glTexCoord4bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const void * pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glTexEnvf, (GLenum target, GLenum pname, GLfloat param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glTexEnvfv, (GLenum target, GLenum pname, const GLfloat * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glTexEnvi, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
-TRACE_GL_VOID(glTexEnviv, (GLenum target, GLenum pname, const GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
-TRACE_GL_VOID(glTexEnvx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glTexEnvxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glTexEnvxv, (GLenum target, GLenum pname, const GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glTexEnvxvOES, (GLenum target, GLenum pname, const GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glTexGenfOES, (GLenum coord, GLenum pname, GLfloat param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glTexGenfvOES, (GLenum coord, GLenum pname, const GLfloat * params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glTexGeniOES, (GLenum coord, GLenum pname, GLint param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLint", param)
-TRACE_GL_VOID(glTexGenivOES, (GLenum coord, GLenum pname, const GLint * params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLint *", params)
-TRACE_GL_VOID(glTexGenxOES, (GLenum coord, GLenum pname, GLfixed param), (coord, pname, param), 3, "GLenum", coord, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glTexGenxvOES, (GLenum coord, GLenum pname, const GLfixed * params), (coord, pname, params), 3, "GLenum", coord, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glTexImage2D, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels), (target, level, internalformat, width, height, border, format, type, pixels), 9, "GLenum", target, "GLint", level, "GLint", internalformat, "GLsizei", width, "GLsizei", height, "GLint", border, "GLenum", format, "GLenum", type, "const void *", pixels)
-TRACE_GL_VOID(glTexImage3D, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels), (target, level, internalformat, width, height, depth, border, format, type, pixels), 10, "GLenum", target, "GLint", level, "GLint", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLenum", format, "GLenum", type, "const void *", pixels)
-TRACE_GL_VOID(glTexImage3DOES, (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels), (target, level, internalformat, width, height, depth, border, format, type, pixels), 10, "GLenum", target, "GLint", level, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLint", border, "GLenum", format, "GLenum", type, "const void *", pixels)
-TRACE_GL_VOID(glTexParameterIivEXT, (GLenum target, GLenum pname, const GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
-TRACE_GL_VOID(glTexParameterIuivEXT, (GLenum target, GLenum pname, const GLuint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLuint *", params)
-TRACE_GL_VOID(glTexParameterf, (GLenum target, GLenum pname, GLfloat param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfloat", param)
-TRACE_GL_VOID(glTexParameterfv, (GLenum target, GLenum pname, const GLfloat * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfloat *", params)
-TRACE_GL_VOID(glTexParameteri, (GLenum target, GLenum pname, GLint param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLint", param)
-TRACE_GL_VOID(glTexParameteriv, (GLenum target, GLenum pname, const GLint * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLint *", params)
-TRACE_GL_VOID(glTexParameterx, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glTexParameterxOES, (GLenum target, GLenum pname, GLfixed param), (target, pname, param), 3, "GLenum", target, "GLenum", pname, "GLfixed", param)
-TRACE_GL_VOID(glTexParameterxv, (GLenum target, GLenum pname, const GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glTexParameterxvOES, (GLenum target, GLenum pname, const GLfixed * params), (target, pname, params), 3, "GLenum", target, "GLenum", pname, "const GLfixed *", params)
-TRACE_GL_VOID(glTexStorage1DEXT, (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width), (target, levels, internalformat, width), 4, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width)
-TRACE_GL_VOID(glTexStorage2D, (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height), (target, levels, internalformat, width, height), 5, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glTexStorage2DEXT, (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height), (target, levels, internalformat, width, height), 5, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glTexStorage2DMultisample, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations), (target, samples, internalformat, width, height, fixedsamplelocations), 6, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLboolean", fixedsamplelocations)
-TRACE_GL_VOID(glTexStorage3D, (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth), (target, levels, internalformat, width, height, depth), 6, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth)
-TRACE_GL_VOID(glTexStorage3DEXT, (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth), (target, levels, internalformat, width, height, depth), 6, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth)
-TRACE_GL_VOID(glTexStorage3DMultisampleOES, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations), (target, samples, internalformat, width, height, depth, fixedsamplelocations), 7, "GLenum", target, "GLsizei", samples, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLboolean", fixedsamplelocations)
-TRACE_GL_VOID(glTexSubImage2D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels), (target, level, xoffset, yoffset, width, height, format, type, pixels), 9, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLsizei", width, "GLsizei", height, "GLenum", format, "GLenum", type, "const void *", pixels)
-TRACE_GL_VOID(glTexSubImage3D, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "const void *", pixels)
-TRACE_GL_VOID(glTexSubImage3DOES, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels), (target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels), 11, "GLenum", target, "GLint", level, "GLint", xoffset, "GLint", yoffset, "GLint", zoffset, "GLsizei", width, "GLsizei", height, "GLsizei", depth, "GLenum", format, "GLenum", type, "const void *", pixels)
-TRACE_GL_VOID(glTextureStorage1DEXT, (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width), (texture, target, levels, internalformat, width), 5, "GLuint", texture, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width)
-TRACE_GL_VOID(glTextureStorage2DEXT, (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height), (texture, target, levels, internalformat, width, height), 6, "GLuint", texture, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glTextureStorage3DEXT, (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth), (texture, target, levels, internalformat, width, height, depth), 7, "GLuint", texture, "GLenum", target, "GLsizei", levels, "GLenum", internalformat, "GLsizei", width, "GLsizei", height, "GLsizei", depth)
-TRACE_GL_VOID(glTextureViewEXT, (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers), (texture, target, origtexture, internalformat, minlevel, numlevels, minlayer, numlayers), 8, "GLuint", texture, "GLenum", target, "GLuint", origtexture, "GLenum", internalformat, "GLuint", minlevel, "GLuint", numlevels, "GLuint", minlayer, "GLuint", numlayers)
-TRACE_GL_VOID(glTransformFeedbackVaryings, (GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode), (program, count, varyings, bufferMode), 4, "GLuint", program, "GLsizei", count, "const GLchar *const*", varyings, "GLenum", bufferMode)
-TRACE_GL_VOID(glTranslatef, (GLfloat x, GLfloat y, GLfloat z), (x, y, z), 3, "GLfloat", x, "GLfloat", y, "GLfloat", z)
-TRACE_GL_VOID(glTranslatex, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
-TRACE_GL_VOID(glTranslatexOES, (GLfixed x, GLfixed y, GLfixed z), (x, y, z), 3, "GLfixed", x, "GLfixed", y, "GLfixed", z)
-TRACE_GL_VOID(glUniform1f, (GLint location, GLfloat v0), (location, v0), 2, "GLint", location, "GLfloat", v0)
-TRACE_GL_VOID(glUniform1fv, (GLint location, GLsizei count, const GLfloat * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glUniform1i, (GLint location, GLint v0), (location, v0), 2, "GLint", location, "GLint", v0)
-TRACE_GL_VOID(glUniform1iv, (GLint location, GLsizei count, const GLint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glUniform1ui, (GLint location, GLuint v0), (location, v0), 2, "GLint", location, "GLuint", v0)
-TRACE_GL_VOID(glUniform1uiv, (GLint location, GLsizei count, const GLuint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glUniform2f, (GLint location, GLfloat v0, GLfloat v1), (location, v0, v1), 3, "GLint", location, "GLfloat", v0, "GLfloat", v1)
-TRACE_GL_VOID(glUniform2fv, (GLint location, GLsizei count, const GLfloat * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glUniform2i, (GLint location, GLint v0, GLint v1), (location, v0, v1), 3, "GLint", location, "GLint", v0, "GLint", v1)
-TRACE_GL_VOID(glUniform2iv, (GLint location, GLsizei count, const GLint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glUniform2ui, (GLint location, GLuint v0, GLuint v1), (location, v0, v1), 3, "GLint", location, "GLuint", v0, "GLuint", v1)
-TRACE_GL_VOID(glUniform2uiv, (GLint location, GLsizei count, const GLuint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glUniform3f, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2), (location, v0, v1, v2), 4, "GLint", location, "GLfloat", v0, "GLfloat", v1, "GLfloat", v2)
-TRACE_GL_VOID(glUniform3fv, (GLint location, GLsizei count, const GLfloat * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glUniform3i, (GLint location, GLint v0, GLint v1, GLint v2), (location, v0, v1, v2), 4, "GLint", location, "GLint", v0, "GLint", v1, "GLint", v2)
-TRACE_GL_VOID(glUniform3iv, (GLint location, GLsizei count, const GLint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glUniform3ui, (GLint location, GLuint v0, GLuint v1, GLuint v2), (location, v0, v1, v2), 4, "GLint", location, "GLuint", v0, "GLuint", v1, "GLuint", v2)
-TRACE_GL_VOID(glUniform3uiv, (GLint location, GLsizei count, const GLuint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glUniform4f, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3), (location, v0, v1, v2, v3), 5, "GLint", location, "GLfloat", v0, "GLfloat", v1, "GLfloat", v2, "GLfloat", v3)
-TRACE_GL_VOID(glUniform4fv, (GLint location, GLsizei count, const GLfloat * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLfloat *", value)
-TRACE_GL_VOID(glUniform4i, (GLint location, GLint v0, GLint v1, GLint v2, GLint v3), (location, v0, v1, v2, v3), 5, "GLint", location, "GLint", v0, "GLint", v1, "GLint", v2, "GLint", v3)
-TRACE_GL_VOID(glUniform4iv, (GLint location, GLsizei count, const GLint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLint *", value)
-TRACE_GL_VOID(glUniform4ui, (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3), (location, v0, v1, v2, v3), 5, "GLint", location, "GLuint", v0, "GLuint", v1, "GLuint", v2, "GLuint", v3)
-TRACE_GL_VOID(glUniform4uiv, (GLint location, GLsizei count, const GLuint * value), (location, count, value), 3, "GLint", location, "GLsizei", count, "const GLuint *", value)
-TRACE_GL_VOID(glUniformBlockBinding, (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding), (program, uniformBlockIndex, uniformBlockBinding), 3, "GLuint", program, "GLuint", uniformBlockIndex, "GLuint", uniformBlockBinding)
-TRACE_GL_VOID(glUniformMatrix2fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix2x3fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix2x3fvNV, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix2x4fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix2x4fvNV, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix3fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix3x2fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix3x2fvNV, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix3x4fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix3x4fvNV, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix4fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix4x2fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix4x2fvNV, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix4x3fv, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL_VOID(glUniformMatrix4x3fvNV, (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value), (location, count, transpose, value), 4, "GLint", location, "GLsizei", count, "GLboolean", transpose, "const GLfloat *", value)
-TRACE_GL(GLboolean, glUnmapBuffer, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL(GLboolean, glUnmapBufferOES, (GLenum target), (target), 1, "GLenum", target)
-TRACE_GL_VOID(glUseProgram, (GLuint program), (program), 1, "GLuint", program)
-TRACE_GL_VOID(glUseProgramStages, (GLuint pipeline, GLbitfield stages, GLuint program), (pipeline, stages, program), 3, "GLuint", pipeline, "GLbitfield", stages, "GLuint", program)
-TRACE_GL_VOID(glUseProgramStagesEXT, (GLuint pipeline, GLbitfield stages, GLuint program), (pipeline, stages, program), 3, "GLuint", pipeline, "GLbitfield", stages, "GLuint", program)
-TRACE_GL_VOID(glValidateProgram, (GLuint program), (program), 1, "GLuint", program)
-TRACE_GL_VOID(glValidateProgramPipeline, (GLuint pipeline), (pipeline), 1, "GLuint", pipeline)
-TRACE_GL_VOID(glValidateProgramPipelineEXT, (GLuint pipeline), (pipeline), 1, "GLuint", pipeline)
-TRACE_GL_VOID(glVertex2bOES, (GLbyte x), (x), 1, "GLbyte", x)
-TRACE_GL_VOID(glVertex2bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glVertex3bOES, (GLbyte x, GLbyte y), (x, y), 2, "GLbyte", x, "GLbyte", y)
-TRACE_GL_VOID(glVertex3bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glVertex4bOES, (GLbyte x, GLbyte y, GLbyte z), (x, y, z), 3, "GLbyte", x, "GLbyte", y, "GLbyte", z)
-TRACE_GL_VOID(glVertex4bvOES, (const GLbyte * coords), (coords), 1, "const GLbyte *", coords)
-TRACE_GL_VOID(glVertexAttrib1f, (GLuint index, GLfloat x), (index, x), 2, "GLuint", index, "GLfloat", x)
-TRACE_GL_VOID(glVertexAttrib1fv, (GLuint index, const GLfloat * v), (index, v), 2, "GLuint", index, "const GLfloat *", v)
-TRACE_GL_VOID(glVertexAttrib2f, (GLuint index, GLfloat x, GLfloat y), (index, x, y), 3, "GLuint", index, "GLfloat", x, "GLfloat", y)
-TRACE_GL_VOID(glVertexAttrib2fv, (GLuint index, const GLfloat * v), (index, v), 2, "GLuint", index, "const GLfloat *", v)
-TRACE_GL_VOID(glVertexAttrib3f, (GLuint index, GLfloat x, GLfloat y, GLfloat z), (index, x, y, z), 4, "GLuint", index, "GLfloat", x, "GLfloat", y, "GLfloat", z)
-TRACE_GL_VOID(glVertexAttrib3fv, (GLuint index, const GLfloat * v), (index, v), 2, "GLuint", index, "const GLfloat *", v)
-TRACE_GL_VOID(glVertexAttrib4f, (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w), (index, x, y, z, w), 5, "GLuint", index, "GLfloat", x, "GLfloat", y, "GLfloat", z, "GLfloat", w)
-TRACE_GL_VOID(glVertexAttrib4fv, (GLuint index, const GLfloat * v), (index, v), 2, "GLuint", index, "const GLfloat *", v)
-TRACE_GL_VOID(glVertexAttribBinding, (GLuint attribindex, GLuint bindingindex), (attribindex, bindingindex), 2, "GLuint", attribindex, "GLuint", bindingindex)
-TRACE_GL_VOID(glVertexAttribDivisor, (GLuint index, GLuint divisor), (index, divisor), 2, "GLuint", index, "GLuint", divisor)
-TRACE_GL_VOID(glVertexAttribDivisorANGLE, (GLuint index, GLuint divisor), (index, divisor), 2, "GLuint", index, "GLuint", divisor)
-TRACE_GL_VOID(glVertexAttribDivisorEXT, (GLuint index, GLuint divisor), (index, divisor), 2, "GLuint", index, "GLuint", divisor)
-TRACE_GL_VOID(glVertexAttribDivisorNV, (GLuint index, GLuint divisor), (index, divisor), 2, "GLuint", index, "GLuint", divisor)
-TRACE_GL_VOID(glVertexAttribFormat, (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset), (attribindex, size, type, normalized, relativeoffset), 5, "GLuint", attribindex, "GLint", size, "GLenum", type, "GLboolean", normalized, "GLuint", relativeoffset)
-TRACE_GL_VOID(glVertexAttribI4i, (GLuint index, GLint x, GLint y, GLint z, GLint w), (index, x, y, z, w), 5, "GLuint", index, "GLint", x, "GLint", y, "GLint", z, "GLint", w)
-TRACE_GL_VOID(glVertexAttribI4iv, (GLuint index, const GLint * v), (index, v), 2, "GLuint", index, "const GLint *", v)
-TRACE_GL_VOID(glVertexAttribI4ui, (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w), (index, x, y, z, w), 5, "GLuint", index, "GLuint", x, "GLuint", y, "GLuint", z, "GLuint", w)
-TRACE_GL_VOID(glVertexAttribI4uiv, (GLuint index, const GLuint * v), (index, v), 2, "GLuint", index, "const GLuint *", v)
-TRACE_GL_VOID(glVertexAttribIFormat, (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset), (attribindex, size, type, relativeoffset), 4, "GLuint", attribindex, "GLint", size, "GLenum", type, "GLuint", relativeoffset)
-TRACE_GL_VOID(glVertexAttribIPointer, (GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer), (index, size, type, stride, pointer), 5, "GLuint", index, "GLint", size, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glVertexAttribPointer, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer), (index, size, type, normalized, stride, pointer), 6, "GLuint", index, "GLint", size, "GLenum", type, "GLboolean", normalized, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glVertexBindingDivisor, (GLuint bindingindex, GLuint divisor), (bindingindex, divisor), 2, "GLuint", bindingindex, "GLuint", divisor)
-TRACE_GL_VOID(glVertexPointer, (GLint size, GLenum type, GLsizei stride, const void * pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const void *", pointer)
-TRACE_GL_VOID(glViewport, (GLint x, GLint y, GLsizei width, GLsizei height), (x, y, width, height), 4, "GLint", x, "GLint", y, "GLsizei", width, "GLsizei", height)
-TRACE_GL_VOID(glWaitSync, (GLsync sync, GLbitfield flags, GLuint64 timeout), (sync, flags, timeout), 3, "GLsync", sync, "GLbitfield", flags, "GLuint64", timeout)
-TRACE_GL_VOID(glWaitSyncAPPLE, (GLsync sync, GLbitfield flags, GLuint64 timeout), (sync, flags, timeout), 3, "GLsync", sync, "GLbitfield", flags, "GLuint64", timeout)
-TRACE_GL_VOID(glWeightPointerOES, (GLint size, GLenum type, GLsizei stride, const void * pointer), (size, type, stride, pointer), 4, "GLint", size, "GLenum", type, "GLsizei", stride, "const void *", pointer)
diff --git a/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt
new file mode 100644
index 0000000..a6fae80
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_create_native_client_buffer.txt
@@ -0,0 +1,197 @@
+Name
+
+    ANDROID_create_native_client_buffer
+
+Name Strings
+
+    EGL_ANDROID_create_native_client_buffer
+
+Contributors
+
+    Craig Donner
+
+Contact
+
+    Craig Donner, Google Inc. (cdonner 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, January 19, 2016
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.2.
+
+    EGL_ANDROID_image_native_buffer and EGL_KHR_image_base are required.
+
+    This extension is written against the wording of the EGL 1.2
+    Specification as modified by EGL_KHR_image_base and
+    EGL_ANDROID_image_native_buffer.
+
+Overview
+
+    This extension allows creating an EGLClientBuffer backed by an Android
+    window buffer (struct ANativeWindowBuffer) which can be later used to
+    create an EGLImage.
+
+New Types
+
+    None.
+
+New Procedures and Functions
+
+EGLClientBuffer eglCreateNativeClientBufferANDROID(
+                        const EGLint *attrib_list)
+
+New Tokens
+
+    EGL_NATIVE_BUFFER_USAGE_ANDROID 0x3143
+    EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID 0x00000001
+    EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID 0x00000002
+    EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID 0x00000004
+
+Changes to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
+
+    Add the following to section 2.5.1 "EGLImage Specification" (as modified by
+    the EGL_KHR_image_base and EGL_ANDROID_image_native_buffer specifications),
+    below the description of eglCreateImageKHR:
+
+   "The command
+
+        EGLClientBuffer eglCreateNativeClientBufferANDROID(
+                                const EGLint *attrib_list)
+
+    may be used to create an EGLClientBuffer backed by an ANativeWindowBuffer
+    struct. EGL implementations must guarantee that the lifetime of the
+    returned EGLClientBuffer is at least as long as the EGLImage(s) it is bound
+    to, following the lifetime semantics described below in section 2.5.2; the
+    EGLClientBuffer must be destroyed no earlier than when all of its associated
+    EGLImages are destroyed by eglDestroyImageKHR. <attrib_list> is a list of
+    attribute-value pairs which is used to specify the dimensions, format, and
+    usage of the underlying buffer structure. If <attrib_list> is non-NULL, the
+    last attribute specified in the list must be EGL_NONE.
+
+    Attribute names accepted in <attrib_list> are shown in Table aaa,
+    together with the <target> for which each attribute name is valid, and
+    the default value used for each attribute if it is not included in
+    <attrib_list>.
+
+      +---------------------------------+----------------------+---------------+
+      | Attribute                       | Description          | Default Value |
+      |                                 |                      |               |
+      +---------------------------------+----------------------+---------------+
+      | EGL_NONE                        | Marks the end of the | N/A           |
+      |                                 | attribute-value list |               |
+      | EGL_WIDTH                       | The width of the     | 0             |
+      |                                 | buffer data          |               |
+      | EGL_HEIGHT                      | The height of the    | 0             |
+      |                                 | buffer data          |               |
+      | EGL_RED_SIZE                    | The bits of Red in   | 0             |
+      |                                 | the color buffer     |               |
+      | EGL_GREEN_SIZE                  | The bits of Green in | 0             |
+      |                                 | the color buffer     |               |
+      | EGL_BLUE_SIZE                   | The bits of Blue in  | 0             |
+      |                                 | the color buffer     |               |
+      | EGL_ALPHA_SIZE                  | The bits of Alpha in | 0             |
+      |                                 | the color buffer     |               |
+      |                                 | buffer data          |               |
+      | EGL_NATIVE_BUFFER_USAGE_ANDROID | The usage bits of    | 0             |
+      |                                 | the buffer data      |               |
+      +---------------------------------+----------------------+---------------+
+       Table aaa.  Legal attributes for eglCreateNativeClientBufferANDROID
+       <attrib_list> parameter.
+
+    The maximum width and height may depend on the amount of available memory,
+    which may also depend on the format and usage flags. The values of
+    EGL_RED_SIZE, EGL_GREEN_SIZE, and EGL_BLUE_SIZE must be non-zero and
+    correspond to a valid pixel format for the implementation. If EGL_ALPHA_SIZE
+    is non-zero then the combination of all four sizes must correspond to a
+    valid pixel format for the implementation. The
+    EGL_NATIVE_BUFFER_USAGE_ANDROID flag may include any of the following bits:
+
+        EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID: Indicates that the
+        created buffer must have a hardware-protected path to external display
+        sink. If a hardware-protected path is not available, then either don't
+        composite only this buffer (preferred) to the external sink, or (less
+        desirable) do not route the entire composition to the external sink.
+
+        EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID: The buffer will be
+        used to create a renderbuffer. This flag must not be set if
+        EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID is set.
+
+        EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID: The buffer will be used to
+        create a texture. This flag must not be set if
+        EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID is set.
+
+    Errors
+
+        If eglCreateNativeClientBufferANDROID fails, NULL will be returned, no
+        memory will be allocated, and one of the following errors will be
+        generated:
+
+       * If the value of EGL_WIDTH or EGL_HEIGHT is not positive, the error
+         EGL_BAD_PARAMETER is generated.
+
+       * If the combination of the values of EGL_RED_SIZE, EGL_GREEN_SIZE,
+         EGL_BLUE_SIZE, and EGL_ALPHA_SIZE is not a valid pixel format for the
+         EGL implementation, the error EGL_BAD_PARAMETER is generated.
+
+       * If the value of EGL_NATIVE_BUFFER_ANDROID is not a valid combination
+         of gralloc usage flags for the EGL implementation, or is incompatible
+         with the value of EGL_FORMAT, the error EGL_BAD_PARAMETER is
+         Generated.
+
+       * If both the EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID and
+         EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID are set in the value of
+         EGL_NATIVE_BUFFER_USAGE_ANDROID, the error EGL_BAD_PARAMETER is
+         Generated."
+
+Issues
+
+    1. Should this extension define what combinations of formats and usage flags
+    EGL implementations are required to support?
+
+    RESOLVED: Partially.
+
+    The set of valid color combinations is implementation-specific and may
+    depend on additional EGL extensions, but generally RGB565 and RGBA888 should
+    be supported. The particular valid combinations for a given Android version
+    and implementation should be documented by that version.
+
+    2. Should there be an eglDestroyNativeClientBufferANDROID to destroy the
+    client buffers created by this extension?
+
+    RESOLVED: No.
+
+    A destroy function would add several complications:
+
+        a) ANativeWindowBuffer is a reference counted object, may be used
+           outside of EGL.
+        b) The same buffer may back multiple EGLImages, though this usage may
+           result in undefined behavior.
+        c) The interactions between the lifetimes of EGLImages and their
+           EGLClientBuffers would become needlessly complex.
+
+    Because ANativeWindowBuffer is a reference counted object, implementations
+    of this extension should ensure the buffer has a lifetime at least as long
+    as a generated EGLImage (via EGL_ANDROID_image_native_buffer). The simplest
+    method is to increment the reference count of the buffer in
+    eglCreateImagKHR, and then decrement it in eglDestroyImageKHR. This should
+    ensure proper lifetime semantics.
+
+Revision History
+
+#2 (Craig Donner, April 15, 2016)
+    - Set color formats and usage bits explicitly using additional attributes,
+    and add value for new token EGL_NATIVE_BUFFER_USAGE_ANDROID.
+
+#1 (Craig Donner, January 19, 2016)
+    - Initial draft.
diff --git a/opengl/specs/EGL_ANDROID_front_buffer_auto_refresh.txt b/opengl/specs/EGL_ANDROID_front_buffer_auto_refresh.txt
new file mode 100644
index 0000000..4c0e64c
--- /dev/null
+++ b/opengl/specs/EGL_ANDROID_front_buffer_auto_refresh.txt
@@ -0,0 +1,70 @@
+Name
+
+    ANDROID_front_buffer_auto_refresh
+
+Name Strings
+
+    EGL_ANDROID_front_buffer_auto_refresh
+
+Contributors
+
+    Pablo Ceballos
+
+Contact
+
+    Pablo Ceballos, Google Inc. (pceballos 'at' google.com)
+
+Status
+
+    Draft
+
+Version
+
+    Version 1, February 3, 2016
+
+Number
+
+    EGL Extension #XXX
+
+Dependencies
+
+    Requires EGL 1.2
+
+    This extension is written against the wording of the EGL 1.5 Specification
+
+Overview
+
+    This extension is intended for latency-sensitive applications that are doing
+    front-buffer rendering. It allows them to indicate to the Android compositor
+    that it should perform composition every time the display refreshes. This
+    removes the overhead of having to notify the compositor that the window
+    surface has been updated, but it comes at the cost of doing potentially
+    unneeded composition work if the window surface has not been updated.
+
+New Types
+
+    None
+
+New Procedures and Functions
+
+    None
+
+New Tokens
+
+    EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID 0x314C
+
+Add to the list of supported tokens for eglSurfaceAttrib in section 3.5.6
+"Surface Attributes", page 43:
+
+    If attribute is EGL_ANDROID_front_buffer_auto_refresh, then value specifies
+    whether to enable or disable auto-refresh in the Android compositor when
+    doing front-buffer rendering.
+
+Issues
+
+    None
+
+Revision History
+
+#1 (Pablo Ceballos, February 3, 2016)
+    - Initial draft.
diff --git a/opengl/specs/README b/opengl/specs/README
index f4de1b3..8f1eaf3 100644
--- a/opengl/specs/README
+++ b/opengl/specs/README
@@ -6,10 +6,10 @@
 
      Value                       Extension
 ----------------     ----------------------------------
-0x3140               EGL_ANDROID_image_native_buffer
-0x3141               (unused)
+0x3140               EGL_NATIVE_BUFFER_ANDROID (EGL_ANDROID_image_native_buffer)
+0x3141               EGL_PLATFORM_ANDROID_KHR (KHR_platform_android)
 0x3142               EGL_RECORDABLE_ANDROID (EGL_ANDROID_recordable)
-0x3143               EGL_VERSION_HW_ANDROID (internal use)
+0x3143               EGL_NATIVE_BUFFER_USAGE_ANDROID (EGL_ANDROID_create_native_client_buffer)
 0x3144               EGL_SYNC_NATIVE_FENCE_ANDROID (EGL_ANDROID_native_fence_sync)
 0x3145               EGL_SYNC_NATIVE_FENCE_FD_ANDROID (EGL_ANDROID_native_fence_sync)
 0x3146               EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID (EGL_ANDROID_native_fence_sync)
@@ -18,4 +18,5 @@
 0x3149               EGL_IMAGE_CROP_TOP_ANDROID (EGL_ANDROID_image_crop)
 0x314A               EGL_IMAGE_CROP_RIGHT_ANDROID (EGL_ANDROID_image_crop)
 0x314B               EGL_IMAGE_CROP_BOTTOM_ANDROID (EGL_ANDROID_image_crop)
-0x314C - 0x314F      (unused)
+0x314C               EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID (EGL_ANDROID_front_buffer_auto_refresh)
+0x314D - 0x314F      (unused)
diff --git a/opengl/tests/gl_perfapp/jni/gl_code.cpp b/opengl/tests/gl_perfapp/jni/gl_code.cpp
index 2f04183..378c8e8 100644
--- a/opengl/tests/gl_perfapp/jni/gl_code.cpp
+++ b/opengl/tests/gl_perfapp/jni/gl_code.cpp
@@ -26,8 +26,6 @@
 // The stateClock starts at zero and increments by 1 every time we draw a frame. It is used to control which phase of the test we are in.
 
 int stateClock;
-const int doLoopStates = 2;
-const int doSingleTestStates = 2;
 bool done;
 
 // Saves the parameters of the test (so we can print them out when we finish the timing.)
diff --git a/opengl/tests/hwc/Android.mk b/opengl/tests/hwc/Android.mk
index f83846b..693fba4 100644
--- a/opengl/tests/hwc/Android.mk
+++ b/opengl/tests/hwc/Android.mk
@@ -19,7 +19,7 @@
 
 LOCAL_MODULE_TAGS := tests
 LOCAL_MODULE:= libhwcTest
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
 LOCAL_CXX_STL := libc++
 LOCAL_SRC_FILES:= hwcTestLib.cpp
 LOCAL_C_INCLUDES += system/extras/tests/include \
@@ -32,7 +32,7 @@
 
 LOCAL_MODULE:= hwcStress
 LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
 LOCAL_CXX_STL := libc++
 LOCAL_SRC_FILES:= hwcStress.cpp
 
@@ -62,7 +62,7 @@
 
 LOCAL_MODULE:= hwcRects
 LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
 LOCAL_CXX_STL := libc++
 LOCAL_SRC_FILES:= hwcRects.cpp
 
@@ -92,7 +92,7 @@
 
 LOCAL_MODULE:= hwcColorEquiv
 LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
 LOCAL_CXX_STL := libc++
 LOCAL_SRC_FILES:= hwcColorEquiv.cpp
 
@@ -122,7 +122,7 @@
 
 LOCAL_MODULE:= hwcCommit
 LOCAL_MODULE_TAGS := tests
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
 LOCAL_CXX_STL := libc++
 LOCAL_SRC_FILES:= hwcCommit.cpp
 
diff --git a/opengl/tests/hwc/hwcColorEquiv.cpp b/opengl/tests/hwc/hwcColorEquiv.cpp
index 06a0191..f1361b8 100644
--- a/opengl/tests/hwc/hwcColorEquiv.cpp
+++ b/opengl/tests/hwc/hwcColorEquiv.cpp
@@ -62,6 +62,8 @@
  *   frame for cases where an equivalent color does not exist.
  */
 
+#define LOG_TAG "hwcColorEquivTest"
+
 #include <algorithm>
 #include <assert.h>
 #include <cerrno>
@@ -87,7 +89,6 @@
 
 #include <ui/GraphicBuffer.h>
 
-#define LOG_TAG "hwcColorEquivTest"
 #include <utils/Log.h>
 #include <testUtil.h>
 
diff --git a/opengl/tests/hwc/hwcCommit.cpp b/opengl/tests/hwc/hwcCommit.cpp
index 1bcb860..6b287e9 100644
--- a/opengl/tests/hwc/hwcCommit.cpp
+++ b/opengl/tests/hwc/hwcCommit.cpp
@@ -70,6 +70,8 @@
  *   made and reported for each of the known graphic format.
  */
 
+#define LOG_TAG "hwcCommitTest"
+
 #include <algorithm>
 #include <assert.h>
 #include <cerrno>
@@ -98,7 +100,6 @@
 
 #include <ui/GraphicBuffer.h>
 
-#define LOG_TAG "hwcCommitTest"
 #include <utils/Log.h>
 #include <testUtil.h>
 
@@ -120,8 +121,6 @@
 const ColorFract defaultColor(0.5, 0.5, 0.5);
 const float      defaultAlpha = 1.0; // Opaque
 const HwcTestDim defaultSourceDim(1, 1);
-const struct hwc_rect defaultSourceCrop = {0, 0, 1, 1};
-const struct hwc_rect defaultDisplayFrame = {0, 0, 100, 100};
 
 // Global Constants
 const uint32_t printFieldWidth = 2;
diff --git a/opengl/tests/hwc/hwcRects.cpp b/opengl/tests/hwc/hwcRects.cpp
index 56c1a2a..2e2b204 100644
--- a/opengl/tests/hwc/hwcRects.cpp
+++ b/opengl/tests/hwc/hwcRects.cpp
@@ -80,6 +80,8 @@
  *   a list of attributes and the format of their expected value.
  */
 
+#define LOG_TAG "hwcRectsTest"
+
 #include <algorithm>
 #include <assert.h>
 #include <cerrno>
@@ -105,8 +107,6 @@
 #include <GLES2/gl2ext.h>
 
 #include <ui/GraphicBuffer.h>
-
-#define LOG_TAG "hwcRectsTest"
 #include <utils/Log.h>
 #include <testUtil.h>
 
diff --git a/opengl/tests/hwc/hwcStress.cpp b/opengl/tests/hwc/hwcStress.cpp
index b1d6c76..60c29ef 100644
--- a/opengl/tests/hwc/hwcStress.cpp
+++ b/opengl/tests/hwc/hwcStress.cpp
@@ -78,6 +78,8 @@
  * a different color from the rest of the rectangle.
  */
 
+#define LOG_TAG "hwcStressTest"
+
 #include <algorithm>
 #include <assert.h>
 #include <cerrno>
@@ -103,7 +105,6 @@
 
 #include <ui/GraphicBuffer.h>
 
-#define LOG_TAG "hwcStressTest"
 #include <utils/Log.h>
 #include <testUtil.h>
 
diff --git a/opengl/tests/lib/Android.mk b/opengl/tests/lib/Android.mk
index e5124ad..4407e7b 100644
--- a/opengl/tests/lib/Android.mk
+++ b/opengl/tests/lib/Android.mk
@@ -22,6 +22,6 @@
 LOCAL_C_INCLUDES += system/extras/tests/include \
 	$(call include-path-for, opengl-tests-includes)
 
-LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES -Wall -Wextra -Werror
 
 include $(BUILD_STATIC_LIBRARY)
diff --git a/opengl/tests/lib/glTestLib.cpp b/opengl/tests/lib/glTestLib.cpp
index b434fc7..213dffd 100644
--- a/opengl/tests/lib/glTestLib.cpp
+++ b/opengl/tests/lib/glTestLib.cpp
@@ -31,7 +31,6 @@
 #include <utils/Log.h>
 #include <testUtil.h>
 
-using namespace std;
 using namespace android;
 
 void glTestPrintGLString(const char *name, GLenum s)
diff --git a/opengl/tools/glgen/convert_to_java.py b/opengl/tools/glgen/convert_to_java.py
new file mode 100644
index 0000000..5254735
--- /dev/null
+++ b/opengl/tools/glgen/convert_to_java.py
@@ -0,0 +1,31 @@
+#!/usr/bin/env python
+#
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+
+# This script is for converting the #defines in the gl2/3.h into the Java
+# form used in the GLES2/3Header.java-if stub files that are then used by
+# the code generator. Provide input with stdin and receive output on stdout.
+
+import sys
+
+allDefines = []
+maxLen = 0
+
+for line in sys.stdin:
+    defineValuePair = line.strip().split()[1:]
+    maxLen = max(maxLen, len(defineValuePair[0]))
+    allDefines.append(defineValuePair)
+for define in sorted(allDefines, key=lambda define: define[1]):
+    print('    public static final int {0[0]:<{1}} = {0[1]};'.format(define, maxLen))
diff --git a/opengl/tools/glgen/gen b/opengl/tools/glgen/gen
index 84a94c8..f9e96ea 100755
--- a/opengl/tools/glgen/gen
+++ b/opengl/tools/glgen/gen
@@ -107,7 +107,8 @@
                     android/opengl/GLES20.java \
                     android/opengl/GLES30.java \
                     android/opengl/GLES31.java \
-                    android/opengl/GLES31Ext.java
+                    android/opengl/GLES31Ext.java \
+                    android/opengl/GLES32.java
 popd > /dev/null
 JAVA_RESULT=$?
 if [ $JAVA_RESULT -ne 0 ]; then
@@ -154,7 +155,7 @@
     compareGenerated ../../../../base/opengl/java/javax/microedition/khronos/opengles generated/javax/microedition/khronos/opengles $x
 done
 
-for x in EGL14 EGLExt GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30 GLES31 GLES31Ext
+for x in EGL14 EGLExt GLES10 GLES10Ext GLES11 GLES11Ext GLES20 GLES30 GLES31 GLES31Ext GLES32
 do
     compareGenerated ../../../../base/opengl/java/android/opengl generated/android/opengl ${x}.java
     compareGenerated ../../../../base/core/jni generated/C android_opengl_${x}.cpp
diff --git a/opengl/tools/glgen/specs/egl/checks.spec b/opengl/tools/glgen/specs/egl/checks.spec
index 34fb1ee..ae531ee 100644
--- a/opengl/tools/glgen/specs/egl/checks.spec
+++ b/opengl/tools/glgen/specs/egl/checks.spec
@@ -1,13 +1,13 @@
-eglInitialize check major 1 check minor 1
-eglGetConfigs check configs config_size
-eglChooseConfig check configs config_size check num_config 1 sentinel attrib_list EGL_NONE
+eglInitialize nullAllowed major nullAllowed minor check major 1 check minor 1
+eglGetConfigs nullAllowed configs check configs config_size
+eglChooseConfig nullAllowed configs check configs config_size check num_config 1 sentinel attrib_list EGL_NONE
 eglGetConfigAttrib check value 1
-//STUB function: //eglCreateWindowSurface sentinel attrib_list EGL_NONE
-eglCreatePbufferSurface sentinel attrib_list EGL_NONE
-//unsupported: eglCreatePixmapSurface sentinel attrib_list EGL_NONE
+//STUB function: //eglCreateWindowSurface nullAllowed attrib_list sentinel attrib_list EGL_NONE
+eglCreatePbufferSurface nullAllowed attrib_list sentinel attrib_list EGL_NONE
+//unsupported: eglCreatePixmapSurface nullAllowed attrib_list sentinel attrib_list EGL_NONE
 eglCreatePixmapSurface unsupported
 eglCopyBuffers unsupported
 eglQuerySurface check value 1
-eglCreatePbufferFromClientBuffer sentinel attrib_list EGL_NONE
+//STUB function: eglCreatePbufferFromClientBuffer nullAllowed attrib_list sentinel attrib_list EGL_NONE
 eglCreateContext sentinel attrib_list EGL_NONE
 eglQueryContext check value 1
diff --git a/opengl/tools/glgen/specs/gles11/GLES30.spec b/opengl/tools/glgen/specs/gles11/GLES30.spec
index a426eb0..f190fc0 100644
--- a/opengl/tools/glgen/specs/gles11/GLES30.spec
+++ b/opengl/tools/glgen/specs/gles11/GLES30.spec
@@ -108,3 +108,4 @@
 void glTexStorage2D ( GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height )
 void glTexStorage3D ( GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth )
 void glGetInternalformativ ( GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params )
+void glReadPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint offset )
diff --git a/opengl/tools/glgen/specs/gles11/GLES32.spec b/opengl/tools/glgen/specs/gles11/GLES32.spec
new file mode 100644
index 0000000..ec60b51
--- /dev/null
+++ b/opengl/tools/glgen/specs/gles11/GLES32.spec
@@ -0,0 +1,44 @@
+void glBlendBarrier ( void )
+void glCopyImageSubData ( GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth )
+void glDebugMessageControl ( GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled )
+void glDebugMessageInsert ( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf )
+void glDebugMessageCallback ( GLDEBUGPROC callback, const void *userParam )
+GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+void glPushDebugGroup ( GLenum source, GLuint id, GLsizei length, const GLchar *message )
+void glPopDebugGroup ( void )
+void glObjectLabel ( GLenum identifier, GLuint name, GLsizei length, const GLchar *label )
+void glGetObjectLabel ( GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label )
+void glObjectPtrLabel ( const void *ptr, GLsizei length, const GLchar *label )
+void glGetObjectPtrLabel ( const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label )
+void glGetPointerv ( GLenum pname, void **params )
+void glEnablei ( GLenum target, GLuint index )
+void glDisablei ( GLenum target, GLuint index )
+void glBlendEquationi ( GLuint buf, GLenum mode )
+void glBlendEquationSeparatei ( GLuint buf, GLenum modeRGB, GLenum modeAlpha )
+void glBlendFunci ( GLuint buf, GLenum src, GLenum dst )
+void glBlendFuncSeparatei ( GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
+void glColorMaski ( GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a )
+GLboolean glIsEnabledi ( GLenum target, GLuint index )
+void glDrawElementsBaseVertex ( GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex )
+void glDrawRangeElementsBaseVertex ( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex )
+void glDrawElementsInstancedBaseVertex ( GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex )
+void glFramebufferTexture ( GLenum target, GLenum attachment, GLuint texture, GLint level )
+void glPrimitiveBoundingBox ( GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW )
+GLenum glGetGraphicsResetStatus ( void )
+void glReadnPixels ( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data )
+void glGetnUniformfv ( GLuint program, GLint location, GLsizei bufSize, GLfloat *params )
+void glGetnUniformiv ( GLuint program, GLint location, GLsizei bufSize, GLint *params )
+void glGetnUniformuiv ( GLuint program, GLint location, GLsizei bufSize, GLuint *params )
+void glMinSampleShading ( GLfloat value )
+void glPatchParameteri ( GLenum pname, GLint value )
+void glTexParameterIiv ( GLenum target, GLenum pname, const GLint *params )
+void glTexParameterIuiv ( GLenum target, GLenum pname, const GLuint *params )
+void glGetTexParameterIiv ( GLenum target, GLenum pname, GLint *params )
+void glGetTexParameterIuiv ( GLenum target, GLenum pname, GLuint *params )
+void glSamplerParameterIiv ( GLuint sampler, GLenum pname, const GLint *param )
+void glSamplerParameterIuiv ( GLuint sampler, GLenum pname, const GLuint *param )
+void glGetSamplerParameterIiv ( GLuint sampler, GLenum pname, GLint *params )
+void glGetSamplerParameterIuiv ( GLuint sampler, GLenum pname, GLuint *params )
+void glTexBuffer ( GLenum target, GLenum internalformat, GLuint buffer )
+void glTexBufferRange ( GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size )
+void glTexStorage3DMultisample ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations )
diff --git a/opengl/tools/glgen/specs/gles11/checks.spec b/opengl/tools/glgen/specs/gles11/checks.spec
index 9eb0070..04413cf 100644
--- a/opengl/tools/glgen/specs/gles11/checks.spec
+++ b/opengl/tools/glgen/specs/gles11/checks.spec
@@ -19,12 +19,14 @@
 # is not perfect but better than nothing.
 #
 
-glBufferData nullAllowed check data size
+glBufferData nullAllowed data check data size
 glBufferSubData check data size
 # glCompressedTexImage2D
 # glCompressedTexSubImage2D
 glClipPlanef check eqn 4
 glClipPlanex check eqn 4
+glDebugMessageControl check ids count
+glDebugMessageInsert check message length
 glDeleteBuffers check buffers n
 glDeleteFramebuffers check framebuffers n
 glDeleteFramebuffersOES check framebuffers n
@@ -32,6 +34,8 @@
 glDeleteRenderbuffersOES check renderbuffers n
 glDeleteTextures check textures n
 glDrawElements check_AIOOBE indices count
+glDrawElementsBaseVertex check_AIOOBE indices count-basevertex
+glDrawRangeElementsBaseVertex check_AIOOBE indices count-basevertex
 glDrawTexfvOES check coords 5
 glDrawTexivOES check coords 5
 glDrawTexsvOES check coords 5
@@ -45,7 +49,7 @@
 glGenTextures check textures n
 // glGetActiveAttrib
 // glGetActiveUniform
-glGetAttachedShaders nullAllowed check count 1 check shaders maxcount
+glGetAttachedShaders nullAllowed count check count 1 check shaders maxcount
 // glGetBooleanv
 glGetBufferParameter check params 1
 glGetClipPlanef check eqn 4
@@ -57,8 +61,10 @@
 // glGetIntegerv
 glGetLight ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
 glGetMaterial ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
+glGetProgramBinary nullAllowed length
 // glGetProgramInfoLog
 glGetProgramiv check params 1
+glGetProgramResourceiv nullAllowed length
 glGetRenderbufferParameteriv check params 1
 glGetRenderbufferParameterivOES check params 1
 // glGetShaderInfoLog
@@ -66,9 +72,13 @@
 glGetShaderPrecisionFormat check range 1 check precision 1
 // glGetShaderSource
 // glGetString
+glGetSynciv nullAllowed length
 glGetTexEnv ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
 glGetTexGen ifcheck params 4 pname GL_OBJECT_PLANE,GL_EYE_PLANE
 glGetTexParameter check params 1
+glGetnUniformfv check params bufSize
+glGetnUniformiv check params bufSize
+glGetnUniformuiv check params bufSize
 glGetUniform check params 1
 glGetVertexAttrib ifcheck params 4 pname GL_CURRENT_VERTEX_ATTRIB
 glLight ifcheck params 3 pname GL_SPOT_DIRECTION ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION
@@ -76,15 +86,20 @@
 glLoadMatrix check m 16
 glMaterial ifcheck params 4 pname GL_AMBIENT,GL_DIFFUSE,GL_SPECULAR,GL_EMISSION,GL_AMBIENT_AND_DIFFUSE
 glMultMatrix check m 16
+glObjectLabelKHR nullAllowed label
+glObjectLabel nullAllowed label check label length
 glPointParameter check params 1
+glPushDebugGroup check message length
 glQueryMatrixxOES check mantissa 16 check exponent 16 return -1
 # glReadPixels
+glReadnPixels check data bufSize
 glShaderBinary check binary length
 // glShaderSource
 glTexEnv ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
-glTexImage2D nullAllowed
+glTexImage2D nullAllowed pixels
+glTexImage3D nullAllowed pixels
 glTexParameter check params 1
-glTexSubImage2D nullAllowed
+glTexSubImage2D nullAllowed pixels
 glUniform1 check v count
 glUniform2 check v count*2
 glUniform3 check v count*3
diff --git a/opengl/tools/glgen/specs/jsr239/glspec-checks b/opengl/tools/glgen/specs/jsr239/glspec-checks
index 9f8a793..750481c 100644
--- a/opengl/tools/glgen/specs/jsr239/glspec-checks
+++ b/opengl/tools/glgen/specs/jsr239/glspec-checks
@@ -19,9 +19,9 @@
 glMultMatrix check m 16
 glPointParameter check params 1
 glTexEnv ifcheck params 1 pname GL_TEXTURE_ENV_MODE,GL_COMBINE_RGB,GL_COMBINE_ALPHA ifcheck params 4 pname GL_TEXTURE_ENV_COLOR
-glTexImage2D nullAllowed
-glTexSubImage2D nullAllowed
-glBufferData nullAllowed check data size
+glTexImage2D nullAllowed pixels
+glTexSubImage2D nullAllowed pixels
+glBufferData nullAllowed data check data size
 glBufferSubData check data size
 glTexParameter check params 1
 glQueryMatrixxOES check mantissa 16 check exponent 16 return -1
diff --git a/opengl/tools/glgen/src/CFunc.java b/opengl/tools/glgen/src/CFunc.java
index a192c00..99c62b5 100644
--- a/opengl/tools/glgen/src/CFunc.java
+++ b/opengl/tools/glgen/src/CFunc.java
@@ -141,7 +141,10 @@
             String tok = tokens[i++];
 
             if (tok.equals("(")) {
-                continue;
+                tok = tokens[i++];
+                if (tok.equals("void")) {
+                    break;
+                }
             }
             if (tok.equals(")")) {
                 break;
@@ -158,10 +161,6 @@
             }
             argType.setBaseType(argTypeName);
 
-            if (argTypeName.equals("void")) {
-                break;
-            }
-
             argName = tokens[i++];
             if (argName.startsWith("*")) {
                 argType.setIsPointer(true);
diff --git a/opengl/tools/glgen/src/GenerateGLES.java b/opengl/tools/glgen/src/GenerateGLES.java
index 5693ef3..cbca682 100644
--- a/opengl/tools/glgen/src/GenerateGLES.java
+++ b/opengl/tools/glgen/src/GenerateGLES.java
@@ -85,7 +85,7 @@
         // Generate files
         for(String suffix: new String[] {"GLES10", "GLES10Ext",
                 "GLES11", "GLES11Ext", "GLES20",
-                "GLES30", "GLES31", "GLES31Ext"})
+                "GLES30", "GLES31", "GLES31Ext", "GLES32"})
         {
             BufferedReader spec11Reader =
                 new BufferedReader(new FileReader("specs/gles11/"
diff --git a/opengl/tools/glgen/src/JType.java b/opengl/tools/glgen/src/JType.java
index 5803a44..7f08503 100644
--- a/opengl/tools/glgen/src/JType.java
+++ b/opengl/tools/glgen/src/JType.java
@@ -44,7 +44,7 @@
     typeMapping.put(new CType("GLuint"), new JType("int"));
     typeMapping.put(new CType("void"), new JType("void"));
     typeMapping.put(new CType("GLubyte", true, true), new JType("String", false, false));
-    typeMapping.put(new CType("char", false, true), new JType("byte"));
+    typeMapping.put(new CType("char"), new JType("byte"));
     typeMapping.put(new CType("char", true, true), new JType("String", false, false));
     typeMapping.put(new CType("GLchar", true, true), new JType("String", false, false));
     typeMapping.put(new CType("int"), new JType("int"));
@@ -75,6 +75,8 @@
             new JType("java.nio.Buffer", true, false));
     typeMapping.put(new CType("void", false, true),
             new JType("java.nio.Buffer", true, false));
+    typeMapping.put(new CType("void", true, true),
+            new JType("java.nio.Buffer", true, false));
     typeMapping.put(new CType("GLeglImageOES", false, false),
             new JType("java.nio.Buffer", true, false));
 
@@ -111,6 +113,8 @@
     // Typed pointers map to arrays + offsets
     arrayTypeMapping.put(new CType("char", false, true),
             new JType("byte", false, true));
+    arrayTypeMapping.put(new CType("GLchar", false, true),
+            new JType("byte", false, true));
     arrayTypeMapping.put(new CType("GLboolean", false, true),
             new JType("boolean", false, true));
     arrayTypeMapping.put(new CType("GLenum", false, true), new JType("int", false, true));
diff --git a/opengl/tools/glgen/src/JniCodeEmitter.java b/opengl/tools/glgen/src/JniCodeEmitter.java
index 1bed05b..6caf076 100644
--- a/opengl/tools/glgen/src/JniCodeEmitter.java
+++ b/opengl/tools/glgen/src/JniCodeEmitter.java
@@ -222,12 +222,13 @@
         needsExit = true;
     }
 
-    boolean isNullAllowed(CFunc cfunc) {
+    boolean isNullAllowed(CFunc cfunc, String cname) {
         String[] checks = mChecker.getChecks(cfunc.getName());
         int index = 1;
         if (checks != null) {
             while (index < checks.length) {
-                if (checks[index].equals("nullAllowed")) {
+                if (checks[index].equals("nullAllowed") &&
+                    checks[index + 1].equals(cname)) {
                     return true;
                 } else {
                     index = skipOneCheck(checks, index);
@@ -252,6 +253,22 @@
         return false;
     }
 
+    boolean hasCheckTest(CFunc cfunc, String cname) {
+        String[] checks = mChecker.getChecks(cfunc.getName());
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("check") &&
+                    cname != null && cname.equals(checks[index + 1])) {
+                    return true;
+                } else {
+                    index = skipOneCheck(checks, index);
+                }
+            }
+        }
+        return false;
+    }
+
     boolean hasIfTest(CFunc cfunc) {
         String[] checks = mChecker.getChecks(cfunc.getName());
         int index = 1;
@@ -281,7 +298,7 @@
         } else if (checks[index].equals("requires")) {
             index += 2;
         } else if (checks[index].equals("nullAllowed")) {
-            index += 1;
+            index += 2;
         } else {
             System.out.println("Error: unknown keyword \"" +
                                checks[index] + "\"");
@@ -469,6 +486,37 @@
         }
     }
 
+    void emitStringCheck(CFunc cfunc, String cname, PrintStream out, String iii) {
+
+        String[] checks = mChecker.getChecks(cfunc.getName());
+
+        int index = 1;
+        if (checks != null) {
+            while (index < checks.length) {
+                if (checks[index].startsWith("check")) {
+                    if (cname != null && !cname.equals(checks[index + 1])) {
+                    index += 3;
+                    continue;
+                }
+                    out.println(iii + "_stringlen = _env->GetStringUTFLength(" + cname + ");");
+                    out.println(iii + "if (" + checks[index + 2] + " > _stringlen) {");
+                    out.println(iii + indent + "_exception = 1;");
+                    out.println(iii + indent +
+                            "_exceptionType = \"java/lang/ArrayIndexOutOfBoundsException\";");
+                    out.println(iii + indent +
+                            "_exceptionMessage = \"length of " + cname + " is shorter than " +
+                            checks[index + 2] + " argument\";");
+                    out.println(iii + indent + "goto exit;");
+                    out.println(iii + "}");
+                    index += 3;
+                    needsExit = true;
+                } else {
+                    index = skipOneCheck(checks, index);
+                }
+            }
+        }
+    }
+
     void emitLocalVariablesForSentinel(CFunc cfunc, PrintStream out) {
 
         String[] checks = mChecker.getChecks(cfunc.getName());
@@ -673,7 +721,7 @@
                         "\";");
         cStream.println();
 
-        cStream.println("static JNINativeMethod methods[] = {");
+        cStream.println("static const JNINativeMethod methods[] = {");
 
         cStream.println("{\"_nativeClassInit\", \"()V\", (void*)nativeClassInit },");
 
@@ -1066,12 +1114,20 @@
 
         // Emit local variable declaration for strings
         if (stringArgs.size() > 0) {
+            boolean requiresStringLengthCheck = false;
             for (int i = 0; i < stringArgs.size(); i++) {
                 int idx = stringArgs.get(i).intValue();
                 int cIndex = jfunc.getArgCIndex(idx);
                 String cname = cfunc.getArgName(cIndex);
 
                 out.println(indent + "const char* _native" + cname + " = 0;");
+                if (hasCheckTest(cfunc, cname)) {
+                    requiresStringLengthCheck = true;
+                }
+            }
+
+            if (requiresStringLengthCheck) {
+                out.println(indent + "jsize _stringlen = 0;");
             }
 
             out.println();
@@ -1084,19 +1140,34 @@
                 int cIndex = jfunc.getArgCIndex(idx);
                 String cname = cfunc.getArgName(cIndex);
 
+                boolean nullAllowed = isNullAllowed(cfunc, cname);
+                String nullAllowedIndent = nullAllowed ? indent : "";
+
                 CType type = cfunc.getArgType(jfunc.getArgCIndex(idx));
                 String decl = type.getDeclaration();
-                needsExit = true;
-                out.println(indent + "if (!" + cname + ") {");
-                out.println(indent + indent + "_exception = 1;");
-                out.println(indent + indent +
-                            "_exceptionType = \"java/lang/IllegalArgumentException\";");
-                out.println(indent + indent +
-                            "_exceptionMessage = \"" + cname + " == null\";");
-                out.println(indent + indent + "goto exit;");
-                out.println(indent + "}");
 
-                out.println(indent + "_native" + cname + " = _env->GetStringUTFChars(" + cname + ", 0);");
+                if (nullAllowed) {
+                    out.println(indent + "if (" + cname + ") {");
+                } else {
+                    needsExit = true;
+                    out.println(indent + "if (!" + cname + ") {");
+                    out.println(indent + indent + "_exception = 1;");
+                    out.println(indent + indent +
+                            "_exceptionType = \"java/lang/IllegalArgumentException\";");
+                    out.println(indent + indent +
+                            "_exceptionMessage = \"" + cname + " == null\";");
+                    out.println(indent + indent + "goto exit;");
+                    out.println(indent + "}");
+                }
+
+                out.println(nullAllowedIndent + indent + "_native" + cname +
+                        " = _env->GetStringUTFChars(" + cname + ", 0);");
+
+                emitStringCheck(cfunc, cname, out, nullAllowedIndent + indent);
+
+                if (nullAllowed) {
+                    out.println(indent + "}");
+                }
             }
 
             out.println();
@@ -1115,85 +1186,126 @@
                 remaining = ((numArrays + numBuffers) <= 1) ? "_remaining" :
                     "_" + cname + "Remaining";
 
+                boolean nullAllowed = isNullAllowed(cfunc, cname);
+                String nullAllowedIndent = nullAllowed ? indent : "";
+
                 if (jfunc.getArgType(idx).isArray()
                        && !jfunc.getArgType(idx).isEGLHandle()) {
                     needsExit = true;
-                    out.println(indent + "if (!" + cname + "_ref) {");
-                    out.println(indent + indent + "_exception = 1;");
-                    out.println(indent + indent +
-                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
-                    out.println(indent + indent +
-                                "_exceptionMessage = \"" + cname +" == null\";");
-                    out.println(indent + indent + "goto exit;");
-                    out.println(indent + "}");
-                    out.println(indent + "if (" + offset + " < 0) {");
-                    out.println(indent + indent + "_exception = 1;");
-                    out.println(indent + indent +
-                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
-                    out.println(indent + indent +
-                                "_exceptionMessage = \"" + offset +" < 0\";");
-                    out.println(indent + indent + "goto exit;");
-                    out.println(indent + "}");
 
-                    out.println(indent + remaining + " = " +
-                                    (mUseCPlusPlus ? "_env" : "(*_env)") +
-                                    "->GetArrayLength(" +
-                                    (mUseCPlusPlus ? "" : "_env, ") +
-                                    cname + "_ref) - " + offset + ";");
+                    if (nullAllowed) {
+                        out.println(indent + "if (" + cname + "_ref) {");
+                    }
+                    else
+                    {
+                        out.println(indent + "if (!" + cname + "_ref) {");
+                        out.println(indent + indent + "_exception = 1;");
+                        out.println(indent + indent +
+                                "_exceptionType = " +
+                                "\"java/lang/IllegalArgumentException\";");
+                        out.println(indent + indent +
+                                "_exceptionMessage = \"" + cname +
+                                " == null\";");
+                        out.println(indent + indent + "goto exit;");
+                        out.println(indent + "}");
+                    }
+
+                    out.println(nullAllowedIndent + indent + "if (" + offset +
+                            " < 0) {");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "_exception = 1;");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "_exceptionType = " +
+                            "\"java/lang/IllegalArgumentException\";");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "_exceptionMessage = \"" + offset +" < 0\";");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "goto exit;");
+                    out.println(nullAllowedIndent + indent + "}");
+
+                    out.println(nullAllowedIndent + indent + remaining + " = " +
+                            (mUseCPlusPlus ? "_env" : "(*_env)") +
+                            "->GetArrayLength(" +
+                            (mUseCPlusPlus ? "" : "_env, ") +
+                            cname + "_ref) - " + offset + ";");
 
                     emitNativeBoundsChecks(cfunc, cname, out, false,
-                                           emitExceptionCheck,
-                                           offset, remaining, "    ");
+                            emitExceptionCheck, offset, remaining,
+                            nullAllowedIndent + indent);
 
-                    out.println(indent +
+                    out.println(nullAllowedIndent + indent +
                                 cname +
                                 "_base = (" +
                                 cfunc.getArgType(cIndex).getDeclaration() +
                                 ")");
                     String arrayGetter = jfunc.getArgType(idx).getArrayGetterForPrimitiveArray();
-                    out.println(indent + "    " +
+                    out.println(nullAllowedIndent + indent + "    " +
                                 (mUseCPlusPlus ? "_env" : "(*_env)") +
                                 "->" + arrayGetter + "(" +
                                 (mUseCPlusPlus ? "" : "_env, ") +
                                 jfunc.getArgName(idx) +
                                 "_ref, (jboolean *)0);");
-                    out.println(indent +
+                    out.println(nullAllowedIndent + indent +
                                 cname + " = " + cname + "_base + " + offset + ";");
 
                     emitSentinelCheck(cfunc, cname, out, false,
-                                      emitExceptionCheck, offset,
-                                      remaining, indent);
+                            emitExceptionCheck, offset, remaining,
+                            nullAllowedIndent + indent);
+
+                    if (nullAllowed) {
+                        out.println(indent + "}");
+                    }
+
                     out.println();
                 } else if (jfunc.getArgType(idx).isArray()
                               && jfunc.getArgType(idx).isEGLHandle()) {
                     needsExit = true;
-                    out.println(indent + "if (!" + cname + "_ref) {");
-                    out.println(indent + indent + "_exception = 1;");
-                    out.println(indent + indent +
-                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
-                    out.println(indent + indent + "_exceptionMessage = \"" + cname +" == null\";");
-                    out.println(indent + indent + "goto exit;");
-                    out.println(indent + "}");
-                    out.println(indent + "if (" + offset + " < 0) {");
-                    out.println(indent + indent + "_exception = 1;");
-                    out.println(indent + indent +
-                                "_exceptionType = \"java/lang/IllegalArgumentException\";");
-                    out.println(indent + indent + "_exceptionMessage = \"" + offset +" < 0\";");
-                    out.println(indent + indent + "goto exit;");
-                    out.println(indent + "}");
 
-                    out.println(indent + remaining + " = " +
+                    if (nullAllowed) {
+                        out.println(indent + "if (" + cname + "_ref) {");
+                    }
+                    else
+                    {
+                        out.println(indent + "if (!" + cname + "_ref) {");
+                        out.println(indent + indent + "_exception = 1;");
+                        out.println(indent + indent + "_exceptionType = " +
+                                "\"java/lang/IllegalArgumentException\";");
+                        out.println(indent + indent + "_exceptionMessage = \"" +
+                                cname +" == null\";");
+                        out.println(indent + indent + "goto exit;");
+                        out.println(indent + "}");
+                    }
+
+                    out.println(nullAllowedIndent + indent + "if (" + offset +
+                            " < 0) {");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "_exception = 1;");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "_exceptionType = " +
+                            "\"java/lang/IllegalArgumentException\";");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "_exceptionMessage = \"" + offset +" < 0\";");
+                    out.println(nullAllowedIndent + indent + indent +
+                            "goto exit;");
+                    out.println(nullAllowedIndent + indent + "}");
+
+                    out.println(nullAllowedIndent + indent + remaining + " = " +
                                     (mUseCPlusPlus ? "_env" : "(*_env)") +
                                     "->GetArrayLength(" +
                                     (mUseCPlusPlus ? "" : "_env, ") +
                                     cname + "_ref) - " + offset + ";");
                     emitNativeBoundsChecks(cfunc, cname, out, false,
-                                           emitExceptionCheck,
-                                           offset, remaining, "    ");
-                    out.println(indent +
+                            emitExceptionCheck, offset, remaining,
+                            nullAllowedIndent + indent);
+                    out.println(nullAllowedIndent + indent +
                                 jfunc.getArgName(idx) + " = new " +
                                 cfunc.getArgType(cIndex).getBaseType() +
                                "["+ remaining + "];");
+
+                    if (nullAllowed) {
+                        out.println(indent + "}");
+                    }
+
                     out.println();
                 } else if (jfunc.getArgType(idx).isBuffer()) {
                     String array = numBufferArgs <= 1 ? "_array" :
@@ -1201,7 +1313,7 @@
                     String bufferOffset = numBufferArgs <= 1 ? "_bufferOffset" :
                         "_" + cfunc.getArgName(cIndex) + "BufferOffset";
 
-                    boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
+                    nullAllowed = nullAllowed || isPointerFunc;
                     if (nullAllowed) {
                         out.println(indent + "if (" + cname + "_buf) {");
                         out.print(indent);
@@ -1254,7 +1366,8 @@
                 String array = numBufferArgs <= 1 ? "_array" :
                             "_" + cfunc.getArgName(cIndex) + "Array";
 
-                boolean nullAllowed = isNullAllowed(cfunc) || isPointerFunc;
+                boolean nullAllowed = isNullAllowed(cfunc, cname) ||
+                        isPointerFunc;
                 if (nullAllowed) {
                     out.println(indent + "if (" + cname + "_buf && " + cname +" == NULL) {");
                 } else {
diff --git a/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp b/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp
index 6199637..497d284 100755
--- a/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglCreatePbufferFromClientBuffer.cpp
@@ -13,34 +13,30 @@
     jint _remaining;
     EGLint *attrib_list = (EGLint *) 0;
 
-    if (!attrib_list_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "attrib_list == null";
-        goto exit;
-    }
-    if (offset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "offset < 0";
-        goto exit;
-    }
-    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
-    attrib_list_base = (EGLint *)
-        _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
-    attrib_list = attrib_list_base + offset;
-    attrib_list_sentinel = false;
-    for (int i = _remaining - 1; i >= 0; i--)  {
-        if (attrib_list[i] == EGL_NONE){
-            attrib_list_sentinel = true;
-            break;
+    if (attrib_list_ref) {
+        if (offset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "offset < 0";
+            goto exit;
         }
-    }
-    if (attrib_list_sentinel == false) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "attrib_list must contain EGL_NONE!";
-        goto exit;
+        _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+        attrib_list_base = (EGLint *)
+            _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
+        attrib_list = attrib_list_base + offset;
+        attrib_list_sentinel = false;
+        for (int i = _remaining - 1; i >= 0; i--)  {
+            if (attrib_list[i] == EGL_NONE){
+                attrib_list_sentinel = true;
+                break;
+            }
+        }
+        if (attrib_list_sentinel == false) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "attrib_list must contain EGL_NONE!";
+            goto exit;
+        }
     }
 
     _returnValue = eglCreatePbufferFromClientBuffer(
diff --git a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
index cc7b85d..355c4b0 100644
--- a/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
+++ b/opengl/tools/glgen/stubs/egl/eglCreateWindowSurface.cpp
@@ -14,18 +14,32 @@
     EGLint *attrib_list = (EGLint *) 0;
     android::sp<ANativeWindow> window;
 
-    if (!attrib_list_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "attrib_list == null";
-        goto exit;
+    if (attrib_list_ref) {
+        if (offset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "offset < 0";
+            goto exit;
+        }
+        _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
+        attrib_list_base = (EGLint *)
+            _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
+        attrib_list = attrib_list_base + offset;
+        attrib_list_sentinel = 0;
+        for (int i = _remaining - 1; i >= 0; i--)  {
+            if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
+                attrib_list_sentinel = 1;
+                break;
+            }
+        }
+        if (attrib_list_sentinel == 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "attrib_list must contain EGL_NONE!";
+            goto exit;
+        }
     }
-    if (offset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "offset < 0";
-        goto exit;
-    }
+
     if (win == NULL) {
 not_valid_surface:
         _exception = 1;
@@ -39,24 +53,6 @@
     if (window == NULL)
         goto not_valid_surface;
 
-    _remaining = _env->GetArrayLength(attrib_list_ref) - offset;
-    attrib_list_base = (EGLint *)
-        _env->GetIntArrayElements(attrib_list_ref, (jboolean *)0);
-    attrib_list = attrib_list_base + offset;
-    attrib_list_sentinel = 0;
-    for (int i = _remaining - 1; i >= 0; i--)  {
-        if (*((EGLint*)(attrib_list + i)) == EGL_NONE){
-            attrib_list_sentinel = 1;
-            break;
-        }
-    }
-    if (attrib_list_sentinel == 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "attrib_list must contain EGL_NONE!";
-        goto exit;
-    }
-
     _returnValue = eglCreateWindowSurface(
         (EGLDisplay)dpy_native,
         (EGLConfig)config_native,
diff --git a/opengl/tools/glgen/stubs/gles11/GLES31Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES31Header.java-if
index 5b45df4..9d67521 100644
--- a/opengl/tools/glgen/stubs/gles11/GLES31Header.java-if
+++ b/opengl/tools/glgen/stubs/gles11/GLES31Header.java-if
@@ -24,9 +24,14 @@
 
     public static final int GL_VERTEX_SHADER_BIT                            = 0x00000001;
     public static final int GL_FRAGMENT_SHADER_BIT                          = 0x00000002;
+    public static final int GL_COMPUTE_SHADER_BIT                           = 0x00000020;
+    public static final int GL_ALL_SHADER_BITS                              = -1; // 0xFFFFFFFF
+
+    public static final int GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT              = 0x00000001;
+    public static final int GL_ELEMENT_ARRAY_BARRIER_BIT                    = 0x00000002;
     public static final int GL_UNIFORM_BARRIER_BIT                          = 0x00000004;
     public static final int GL_TEXTURE_FETCH_BARRIER_BIT                    = 0x00000008;
-    public static final int GL_COMPUTE_SHADER_BIT                           = 0x00000020;
+    public static final int GL_SHADER_IMAGE_ACCESS_BARRIER_BIT              = 0x00000020;
     public static final int GL_COMMAND_BARRIER_BIT                          = 0x00000040;
     public static final int GL_PIXEL_BUFFER_BARRIER_BIT                     = 0x00000080;
     public static final int GL_TEXTURE_UPDATE_BARRIER_BIT                   = 0x00000100;
@@ -35,7 +40,8 @@
     public static final int GL_TRANSFORM_FEEDBACK_BARRIER_BIT               = 0x00000800;
     public static final int GL_ATOMIC_COUNTER_BARRIER_BIT                   = 0x00001000;
     public static final int GL_SHADER_STORAGE_BARRIER_BIT                   = 0x00002000;
-    public static final int GL_ALL_SHADER_BITS                              = -1; // 0xFFFFFFFF
+    public static final int GL_ALL_BARRIER_BITS                             = -1; // 0xFFFFFFFF
+
 
     public static final int GL_TEXTURE_WIDTH                                = 0x1000;
     public static final int GL_TEXTURE_HEIGHT                               = 0x1001;
@@ -198,4 +204,5 @@
         _nativeClassInit();
     }
 
-    private GLES31() {}
+    /** @hide */
+    GLES31() {}
diff --git a/opengl/tools/glgen/stubs/gles11/GLES32Header.java-if b/opengl/tools/glgen/stubs/gles11/GLES32Header.java-if
new file mode 100644
index 0000000..b526cb7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES32Header.java-if
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// This source file is automatically generated
+
+package android.opengl;
+
+/** OpenGL ES 3.2
+ */
+public class GLES32 extends GLES31 {
+
+    public static final int GL_CONTEXT_FLAG_DEBUG_BIT                          = 0x00000002;
+
+    public static final int GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT                  = 0x00000004;
+
+    public static final int GL_GEOMETRY_SHADER_BIT                             = 0x00000004;
+    public static final int GL_TESS_CONTROL_SHADER_BIT                         = 0x00000008;
+    public static final int GL_TESS_EVALUATION_SHADER_BIT                      = 0x00000010;
+
+    public static final int GL_QUADS                                           = 0x0007;
+    public static final int GL_LINES_ADJACENCY                                 = 0x000A;
+    public static final int GL_LINE_STRIP_ADJACENCY                            = 0x000B;
+    public static final int GL_TRIANGLES_ADJACENCY                             = 0x000C;
+    public static final int GL_TRIANGLE_STRIP_ADJACENCY                        = 0x000D;
+    public static final int GL_PATCHES                                         = 0x000E;
+    public static final int GL_STACK_OVERFLOW                                  = 0x0503;
+    public static final int GL_STACK_UNDERFLOW                                 = 0x0504;
+    public static final int GL_CONTEXT_LOST                                    = 0x0507;
+    public static final int GL_TEXTURE_BORDER_COLOR                            = 0x1004;
+    public static final int GL_VERTEX_ARRAY                                    = 0x8074;
+    public static final int GL_CLAMP_TO_BORDER                                 = 0x812D;
+    public static final int GL_CONTEXT_FLAGS                                   = 0x821E;
+    public static final int GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED         = 0x8221;
+    public static final int GL_DEBUG_OUTPUT_SYNCHRONOUS                        = 0x8242;
+    public static final int GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH                = 0x8243;
+    public static final int GL_DEBUG_CALLBACK_FUNCTION                         = 0x8244;
+    public static final int GL_DEBUG_CALLBACK_USER_PARAM                       = 0x8245;
+    public static final int GL_DEBUG_SOURCE_API                                = 0x8246;
+    public static final int GL_DEBUG_SOURCE_WINDOW_SYSTEM                      = 0x8247;
+    public static final int GL_DEBUG_SOURCE_SHADER_COMPILER                    = 0x8248;
+    public static final int GL_DEBUG_SOURCE_THIRD_PARTY                        = 0x8249;
+    public static final int GL_DEBUG_SOURCE_APPLICATION                        = 0x824A;
+    public static final int GL_DEBUG_SOURCE_OTHER                              = 0x824B;
+    public static final int GL_DEBUG_TYPE_ERROR                                = 0x824C;
+    public static final int GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR                  = 0x824D;
+    public static final int GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR                   = 0x824E;
+    public static final int GL_DEBUG_TYPE_PORTABILITY                          = 0x824F;
+    public static final int GL_DEBUG_TYPE_PERFORMANCE                          = 0x8250;
+    public static final int GL_DEBUG_TYPE_OTHER                                = 0x8251;
+    public static final int GL_LOSE_CONTEXT_ON_RESET                           = 0x8252;
+    public static final int GL_GUILTY_CONTEXT_RESET                            = 0x8253;
+    public static final int GL_INNOCENT_CONTEXT_RESET                          = 0x8254;
+    public static final int GL_UNKNOWN_CONTEXT_RESET                           = 0x8255;
+    public static final int GL_RESET_NOTIFICATION_STRATEGY                     = 0x8256;
+    public static final int GL_LAYER_PROVOKING_VERTEX                          = 0x825E;
+    public static final int GL_UNDEFINED_VERTEX                                = 0x8260;
+    public static final int GL_NO_RESET_NOTIFICATION                           = 0x8261;
+    public static final int GL_DEBUG_TYPE_MARKER                               = 0x8268;
+    public static final int GL_DEBUG_TYPE_PUSH_GROUP                           = 0x8269;
+    public static final int GL_DEBUG_TYPE_POP_GROUP                            = 0x826A;
+    public static final int GL_DEBUG_SEVERITY_NOTIFICATION                     = 0x826B;
+    public static final int GL_MAX_DEBUG_GROUP_STACK_DEPTH                     = 0x826C;
+    public static final int GL_DEBUG_GROUP_STACK_DEPTH                         = 0x826D;
+    public static final int GL_BUFFER                                          = 0x82E0;
+    public static final int GL_SHADER                                          = 0x82E1;
+    public static final int GL_PROGRAM                                         = 0x82E2;
+    public static final int GL_QUERY                                           = 0x82E3;
+    public static final int GL_PROGRAM_PIPELINE                                = 0x82E4;
+    public static final int GL_SAMPLER                                         = 0x82E6;
+    public static final int GL_MAX_LABEL_LENGTH                                = 0x82E8;
+    public static final int GL_MAX_TESS_CONTROL_INPUT_COMPONENTS               = 0x886C;
+    public static final int GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS            = 0x886D;
+    public static final int GL_GEOMETRY_SHADER_INVOCATIONS                     = 0x887F;
+    public static final int GL_GEOMETRY_VERTICES_OUT                           = 0x8916;
+    public static final int GL_GEOMETRY_INPUT_TYPE                             = 0x8917;
+    public static final int GL_GEOMETRY_OUTPUT_TYPE                            = 0x8918;
+    public static final int GL_MAX_GEOMETRY_UNIFORM_BLOCKS                     = 0x8A2C;
+    public static final int GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS        = 0x8A32;
+    public static final int GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS                = 0x8C29;
+    public static final int GL_TEXTURE_BUFFER                                  = 0x8C2A;
+    public static final int GL_TEXTURE_BUFFER_BINDING                          = 0x8C2A;
+    public static final int GL_MAX_TEXTURE_BUFFER_SIZE                         = 0x8C2B;
+    public static final int GL_TEXTURE_BINDING_BUFFER                          = 0x8C2C;
+    public static final int GL_TEXTURE_BUFFER_DATA_STORE_BINDING               = 0x8C2D;
+    public static final int GL_SAMPLE_SHADING                                  = 0x8C36;
+    public static final int GL_MIN_SAMPLE_SHADING_VALUE                        = 0x8C37;
+    public static final int GL_PRIMITIVES_GENERATED                            = 0x8C87;
+    public static final int GL_FRAMEBUFFER_ATTACHMENT_LAYERED                  = 0x8DA7;
+    public static final int GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS            = 0x8DA8;
+    public static final int GL_SAMPLER_BUFFER                                  = 0x8DC2;
+    public static final int GL_INT_SAMPLER_BUFFER                              = 0x8DD0;
+    public static final int GL_UNSIGNED_INT_SAMPLER_BUFFER                     = 0x8DD8;
+    public static final int GL_GEOMETRY_SHADER                                 = 0x8DD9;
+    public static final int GL_MAX_GEOMETRY_UNIFORM_COMPONENTS                 = 0x8DDF;
+    public static final int GL_MAX_GEOMETRY_OUTPUT_VERTICES                    = 0x8DE0;
+    public static final int GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS            = 0x8DE1;
+    public static final int GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS    = 0x8E1E;
+    public static final int GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS = 0x8E1F;
+    public static final int GL_FIRST_VERTEX_CONVENTION                         = 0x8E4D;
+    public static final int GL_LAST_VERTEX_CONVENTION                          = 0x8E4E;
+    public static final int GL_MAX_GEOMETRY_SHADER_INVOCATIONS                 = 0x8E5A;
+    public static final int GL_MIN_FRAGMENT_INTERPOLATION_OFFSET               = 0x8E5B;
+    public static final int GL_MAX_FRAGMENT_INTERPOLATION_OFFSET               = 0x8E5C;
+    public static final int GL_FRAGMENT_INTERPOLATION_OFFSET_BITS              = 0x8E5D;
+    public static final int GL_PATCH_VERTICES                                  = 0x8E72;
+    public static final int GL_TESS_CONTROL_OUTPUT_VERTICES                    = 0x8E75;
+    public static final int GL_TESS_GEN_MODE                                   = 0x8E76;
+    public static final int GL_TESS_GEN_SPACING                                = 0x8E77;
+    public static final int GL_TESS_GEN_VERTEX_ORDER                           = 0x8E78;
+    public static final int GL_TESS_GEN_POINT_MODE                             = 0x8E79;
+    public static final int GL_ISOLINES                                        = 0x8E7A;
+    public static final int GL_FRACTIONAL_ODD                                  = 0x8E7B;
+    public static final int GL_FRACTIONAL_EVEN                                 = 0x8E7C;
+    public static final int GL_MAX_PATCH_VERTICES                              = 0x8E7D;
+    public static final int GL_MAX_TESS_GEN_LEVEL                              = 0x8E7E;
+    public static final int GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS             = 0x8E7F;
+    public static final int GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS          = 0x8E80;
+    public static final int GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS            = 0x8E81;
+    public static final int GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS         = 0x8E82;
+    public static final int GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS              = 0x8E83;
+    public static final int GL_MAX_TESS_PATCH_COMPONENTS                       = 0x8E84;
+    public static final int GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS        = 0x8E85;
+    public static final int GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS           = 0x8E86;
+    public static final int GL_TESS_EVALUATION_SHADER                          = 0x8E87;
+    public static final int GL_TESS_CONTROL_SHADER                             = 0x8E88;
+    public static final int GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS                 = 0x8E89;
+    public static final int GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS              = 0x8E8A;
+    public static final int GL_TEXTURE_CUBE_MAP_ARRAY                          = 0x9009;
+    public static final int GL_TEXTURE_BINDING_CUBE_MAP_ARRAY                  = 0x900A;
+    public static final int GL_SAMPLER_CUBE_MAP_ARRAY                          = 0x900C;
+    public static final int GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW                   = 0x900D;
+    public static final int GL_INT_SAMPLER_CUBE_MAP_ARRAY                      = 0x900E;
+    public static final int GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY             = 0x900F;
+    public static final int GL_IMAGE_BUFFER                                    = 0x9051;
+    public static final int GL_IMAGE_CUBE_MAP_ARRAY                            = 0x9054;
+    public static final int GL_INT_IMAGE_BUFFER                                = 0x905C;
+    public static final int GL_INT_IMAGE_CUBE_MAP_ARRAY                        = 0x905F;
+    public static final int GL_UNSIGNED_INT_IMAGE_BUFFER                       = 0x9067;
+    public static final int GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY               = 0x906A;
+    public static final int GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS                 = 0x90CB;
+    public static final int GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS              = 0x90CC;
+    public static final int GL_MAX_GEOMETRY_IMAGE_UNIFORMS                     = 0x90CD;
+    public static final int GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS              = 0x90D7;
+    public static final int GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS          = 0x90D8;
+    public static final int GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS       = 0x90D9;
+    public static final int GL_TEXTURE_2D_MULTISAMPLE_ARRAY                    = 0x9102;
+    public static final int GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY            = 0x9105;
+    public static final int GL_SAMPLER_2D_MULTISAMPLE_ARRAY                    = 0x910B;
+    public static final int GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY                = 0x910C;
+    public static final int GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY       = 0x910D;
+    public static final int GL_MAX_GEOMETRY_INPUT_COMPONENTS                   = 0x9123;
+    public static final int GL_MAX_GEOMETRY_OUTPUT_COMPONENTS                  = 0x9124;
+    public static final int GL_MAX_DEBUG_MESSAGE_LENGTH                        = 0x9143;
+    public static final int GL_MAX_DEBUG_LOGGED_MESSAGES                       = 0x9144;
+    public static final int GL_DEBUG_LOGGED_MESSAGES                           = 0x9145;
+    public static final int GL_DEBUG_SEVERITY_HIGH                             = 0x9146;
+    public static final int GL_DEBUG_SEVERITY_MEDIUM                           = 0x9147;
+    public static final int GL_DEBUG_SEVERITY_LOW                              = 0x9148;
+    public static final int GL_TEXTURE_BUFFER_OFFSET                           = 0x919D;
+    public static final int GL_TEXTURE_BUFFER_SIZE                             = 0x919E;
+    public static final int GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT                 = 0x919F;
+    public static final int GL_MULTIPLY                                        = 0x9294;
+    public static final int GL_SCREEN                                          = 0x9295;
+    public static final int GL_OVERLAY                                         = 0x9296;
+    public static final int GL_DARKEN                                          = 0x9297;
+    public static final int GL_LIGHTEN                                         = 0x9298;
+    public static final int GL_COLORDODGE                                      = 0x9299;
+    public static final int GL_COLORBURN                                       = 0x929A;
+    public static final int GL_HARDLIGHT                                       = 0x929B;
+    public static final int GL_SOFTLIGHT                                       = 0x929C;
+    public static final int GL_DIFFERENCE                                      = 0x929E;
+    public static final int GL_EXCLUSION                                       = 0x92A0;
+    public static final int GL_HSL_HUE                                         = 0x92AD;
+    public static final int GL_HSL_SATURATION                                  = 0x92AE;
+    public static final int GL_HSL_COLOR                                       = 0x92AF;
+    public static final int GL_HSL_LUMINOSITY                                  = 0x92B0;
+    public static final int GL_PRIMITIVE_BOUNDING_BOX                          = 0x92BE;
+    public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS         = 0x92CD;
+    public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS      = 0x92CE;
+    public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS             = 0x92CF;
+    public static final int GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS                = 0x92D3;
+    public static final int GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS             = 0x92D4;
+    public static final int GL_MAX_GEOMETRY_ATOMIC_COUNTERS                    = 0x92D5;
+    public static final int GL_DEBUG_OUTPUT                                    = 0x92E0;
+    public static final int GL_IS_PER_PATCH                                    = 0x92E7;
+    public static final int GL_REFERENCED_BY_TESS_CONTROL_SHADER               = 0x9307;
+    public static final int GL_REFERENCED_BY_TESS_EVALUATION_SHADER            = 0x9308;
+    public static final int GL_REFERENCED_BY_GEOMETRY_SHADER                   = 0x9309;
+    public static final int GL_FRAMEBUFFER_DEFAULT_LAYERS                      = 0x9312;
+    public static final int GL_MAX_FRAMEBUFFER_LAYERS                          = 0x9317;
+    public static final int GL_MULTISAMPLE_LINE_WIDTH_RANGE                    = 0x9381;
+    public static final int GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY              = 0x9382;
+    public static final int GL_COMPRESSED_RGBA_ASTC_4x4                        = 0x93B0;
+    public static final int GL_COMPRESSED_RGBA_ASTC_5x4                        = 0x93B1;
+    public static final int GL_COMPRESSED_RGBA_ASTC_5x5                        = 0x93B2;
+    public static final int GL_COMPRESSED_RGBA_ASTC_6x5                        = 0x93B3;
+    public static final int GL_COMPRESSED_RGBA_ASTC_6x6                        = 0x93B4;
+    public static final int GL_COMPRESSED_RGBA_ASTC_8x5                        = 0x93B5;
+    public static final int GL_COMPRESSED_RGBA_ASTC_8x6                        = 0x93B6;
+    public static final int GL_COMPRESSED_RGBA_ASTC_8x8                        = 0x93B7;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x5                       = 0x93B8;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x6                       = 0x93B9;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x8                       = 0x93BA;
+    public static final int GL_COMPRESSED_RGBA_ASTC_10x10                      = 0x93BB;
+    public static final int GL_COMPRESSED_RGBA_ASTC_12x10                      = 0x93BC;
+    public static final int GL_COMPRESSED_RGBA_ASTC_12x12                      = 0x93BD;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4                = 0x93D0;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4                = 0x93D1;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5                = 0x93D2;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5                = 0x93D3;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6                = 0x93D4;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5                = 0x93D5;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6                = 0x93D6;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8                = 0x93D7;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5               = 0x93D8;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6               = 0x93D9;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8               = 0x93DA;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10              = 0x93DB;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10              = 0x93DC;
+    public static final int GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12              = 0x93DD;
+
+
+    native private static void _nativeClassInit();
+    static {
+        _nativeClassInit();
+    }
+
+    private GLES32() {}
diff --git a/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
new file mode 100644
index 0000000..e9c5fc7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/GLES32cHeader.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// This source file is automatically generated
+
+#pragma GCC diagnostic ignored "-Wunused-variable"
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#pragma GCC diagnostic ignored "-Wunused-function"
+
+#include <stdint.h>
+#include <GLES3/gl32.h>
\ No newline at end of file
diff --git a/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp b/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp
index e701481..52295a1 100644
--- a/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glCreateShaderProgramv.cpp
@@ -2,7 +2,67 @@
 static jint
 android_glCreateShaderProgramv
   (JNIEnv *_env, jobject _this, jint type, jobjectArray strings) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    GLsizei _count;
+    const GLchar** _strings = NULL;
+    jstring* _jstrings = NULL;
+    GLuint _returnValue = 0;
 
-    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
-    return 0;
+    if (!strings) {
+        _exception = 1;
+        _exceptionType = "java/lang/IllegalArgumentException";
+        _exceptionMessage = "strings == null";
+        goto exit;
+    }
+
+    _count = _env->GetArrayLength(strings);
+
+    _strings = (const GLchar**) calloc(_count, sizeof(const GLchar*));
+    if (!_strings) {
+        _exception = 1;
+        _exceptionType = "java/lang/OutOfMemoryError";
+        _exceptionMessage = "out of memory";
+        goto exit;
+    }
+
+    _jstrings = (jstring*) calloc(_count, sizeof(jstring));
+    if (!_jstrings) {
+        _exception = 1;
+        _exceptionType = "java/lang/OutOfMemoryError";
+        _exceptionMessage = "out of memory";
+        goto exit;
+    }
+
+    for(int i = 0; i < _count; i++) {
+        _jstrings[i] = (jstring) _env->GetObjectArrayElement(strings, i);
+        if (!_jstrings[i]) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "strings == null";
+            goto exit;
+        }
+        _strings[i] = _env->GetStringUTFChars(_jstrings[i], 0);
+    }
+
+    _returnValue = glCreateShaderProgramv((GLenum)type, _count, _strings);
+exit:
+    if (_strings && _jstrings) {
+        for(int i = 0; i < _count; i++) {
+            if (_strings[i] && _jstrings[i]) {
+                _env->ReleaseStringUTFChars(_jstrings[i], _strings[i]);
+            }
+        }
+    }
+    if (_strings) {
+        free(_strings);
+    }
+    if (_jstrings) {
+        free(_jstrings);
+    }
+    if (_exception) {
+        jniThrowException(_env, _exceptionType, _exceptionMessage);
+    }
+    return (jint)_returnValue;
 }
diff --git a/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.cpp b/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.cpp
new file mode 100644
index 0000000..a5329d6
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.cpp
@@ -0,0 +1,5 @@
+/* void glDebugMessageCallback ( GLDEBUGPROC callback, const void *userParam ) */
+static void
+android_glDebugMessageCallback(JNIEnv *_env, jobject _this, jobject callback) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.java b/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.java
new file mode 100644
index 0000000..21cbef3
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.java
@@ -0,0 +1,8 @@
+    // C function void glDebugMessageCallback ( GLDEBUGPROC callback, const void *userParam )
+
+    public interface DebugProc {
+        void onMessage(int source, int type, int id, int severity, String message);
+    }
+
+    public static native void glDebugMessageCallback(DebugProc callback);
+
diff --git a/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.nativeReg b/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.nativeReg
new file mode 100644
index 0000000..589df79
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glDebugMessageCallback.nativeReg
@@ -0,0 +1 @@
+{"glDebugMessageCallback", "(Landroid/opengl/GLES32$DebugProc;)V", (void *) android_glDebugMessageCallback },
diff --git a/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.cpp b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.cpp
new file mode 100644
index 0000000..4e253b7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.cpp
@@ -0,0 +1,51 @@
+/* void glDrawElementsInstancedBaseVertex ( GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount, GLint basevertex ) */
+static void
+android_glDrawElementsInstancedBaseVertex__IIILjava_nio_Buffer_2II
+  (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jobject indices_buf, jint instanceCount, jint basevertex) {
+    jint _exception = 0;
+    const char * _exceptionType = NULL;
+    const char * _exceptionMessage = NULL;
+    jarray _array = (jarray) 0;
+    jint _bufferOffset = (jint) 0;
+    jint _remaining;
+    void *indices = (void *) 0;
+
+    indices = (void *)getPointer(_env, indices_buf, &_array, &_remaining, &_bufferOffset);
+    if (_remaining < count-basevertex) {
+        _exception = 1;
+        _exceptionType = "java/lang/ArrayIndexOutOfBoundsException";
+        _exceptionMessage = "remaining() < count-basevertex < needed";
+        goto exit;
+    }
+    if (indices == NULL) {
+        char * _indicesBase = (char *)_env->GetPrimitiveArrayCritical(_array, (jboolean *) 0);
+        indices = (void *) (_indicesBase + _bufferOffset);
+    }
+    glDrawElementsInstancedBaseVertex(
+        (GLenum)mode,
+        (GLsizei)count,
+        (GLenum)type,
+        (void *)indices,
+        (GLsizei)instanceCount,
+        (GLint) basevertex
+    );
+
+exit:
+    if (_array) {
+        releasePointer(_env, _array, indices, JNI_FALSE);
+    }
+}
+
+/* void glDrawElementsInstancedBaseVertex ( GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount, GLint basevertex ) */
+static void
+android_glDrawElementsInstancedBaseVertex__IIIIII
+  (JNIEnv *_env, jobject _this, jint mode, jint count, jint type, jint indicesOffset, jint instanceCount, jint basevertex) {
+    glDrawElementsInstancedBaseVertex(
+        (GLenum)mode,
+        (GLsizei)count,
+        (GLenum)type,
+        (void *)static_cast<uintptr_t>(indicesOffset),
+        (GLsizei)instanceCount,
+        (GLint)basevertex
+    );
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.java b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.java
new file mode 100644
index 0000000..2aad293
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.java
@@ -0,0 +1,22 @@
+    // C function void glDrawElementsInstancedBaseVertex ( GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount, GLint basevertex )
+
+    public static native void glDrawElementsInstancedBaseVertex(
+        int mode,
+        int count,
+        int type,
+        java.nio.Buffer indices,
+        int instanceCount,
+        int basevertex
+    );
+
+    // C function void glDrawElementsInstancedBaseVertex ( GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instanceCount, GLint basevertex )
+
+    public static native void glDrawElementsInstancedBaseVertex(
+        int mode,
+        int count,
+        int type,
+        int indicesOffset,
+        int instanceCount,
+        int basevertex
+    );
+
diff --git a/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.nativeReg b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.nativeReg
new file mode 100644
index 0000000..5faafa6
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glDrawElementsInstancedBaseVertex.nativeReg
@@ -0,0 +1,2 @@
+{"glDrawElementsInstancedBaseVertex", "(IIILjava/nio/Buffer;II)V", (void *) android_glDrawElementsInstancedBaseVertex__IIILjava_nio_Buffer_2II },
+{"glDrawElementsInstancedBaseVertex", "(IIIIII)V", (void *) android_glDrawElementsInstancedBaseVertex__IIIIII },
diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp b/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp
index a8d63d9..6cdbf71 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetActiveAttrib.cpp
@@ -18,22 +18,18 @@
     jint _nameRemaining;
     char *name = (char *) 0;
 
-    if (!length_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "length == null";
-        goto exit;
+    if (length_ref) {
+        if (lengthOffset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "lengthOffset < 0";
+            goto exit;
+        }
+        _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+        length_base = (GLsizei *)
+            _env->GetIntArrayElements(length_ref, (jboolean *)0);
+        length = length_base + lengthOffset;
     }
-    if (lengthOffset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "lengthOffset < 0";
-        goto exit;
-    }
-    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
-    length_base = (GLsizei *)
-        _env->GetIntArrayElements(length_ref, (jboolean *)0);
-    length = length_base + lengthOffset;
 
     if (!size_ref) {
         _exception = 1;
diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp b/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp
index 68e8389..07094bd 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetActiveUniform.cpp
@@ -18,22 +18,18 @@
     jint _nameRemaining;
     char *name = (char *) 0;
 
-    if (!length_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "length == null";
-        goto exit;
+    if (length_ref) {
+        if (lengthOffset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "lengthOffset < 0";
+            goto exit;
+        }
+        _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+        length_base = (GLsizei *)
+            _env->GetIntArrayElements(length_ref, (jboolean *)0);
+        length = length_base + lengthOffset;
     }
-    if (lengthOffset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "lengthOffset < 0";
-        goto exit;
-    }
-    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
-    length_base = (GLsizei *)
-        _env->GetIntArrayElements(length_ref, (jboolean *)0);
-    length = length_base + lengthOffset;
 
     if (!size_ref) {
         _exception = 1;
diff --git a/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp b/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp
index 6104c84..24086e4 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetActiveUniformBlockName.cpp
@@ -12,22 +12,18 @@
     jint _nameRemaining;
     GLchar* _name = (GLchar*)0;
 
-    if (!length_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "length == null";
-        goto exit;
+    if (length_ref) {
+        if (lengthOffset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "lengthOffset < 0";
+            goto exit;
+        }
+        _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+        _length_base = (GLsizei*)_env->GetIntArrayElements(
+                length_ref, (jboolean*)0);
+        _length = _length_base + lengthOffset;
     }
-    if (lengthOffset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "lengthOffset < 0";
-        goto exit;
-    }
-    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
-    _length_base = (GLsizei*)_env->GetIntArrayElements(
-            length_ref, (jboolean*)0);
-    _length = _length_base + lengthOffset;
 
     if (!name_ref) {
         _exception = 1;
diff --git a/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.cpp b/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.cpp
new file mode 100644
index 0000000..0a37d97
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.cpp
@@ -0,0 +1,31 @@
+/* GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static jint
+android_glGetDebugMessageLog__II_3II_3II_3II_3II_3II_3BI
+  (JNIEnv *_env, jobject _this, jint count, jint bufSize, jintArray sources_ref, jint sourcesOffset, jintArray types_ref, jint typesOffset, jintArray ids_ref, jint idsOffset, jintArray severities_ref, jint severitiesOffset, jintArray lengths_ref, jint lengthsOffset, jbyteArray messageLog_ref, jint messageLogOffset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+
+/* GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static uint
+android_glGetDebugMessageLog__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+  (JNIEnv *_env, jobject _this, jint count, jobject sources_ref, jobject types_ref, jobject ids_ref, jobject severities_ref, jobject lengths_ref, jobject messageLog_ref) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+
+/* GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static jobjectArray
+android_glGetDebugMessageLog__I_3II_3II_3II_3II
+  (JNIEnv *_env, jobject _this, jint count, jintArray sources_ref, jint sourcesOffset, jintArray types_ref, jint typesOffset, jintArray ids_ref, jint idsOffset, jintArray severities_ref, jint severitiesOffset) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
+
+/* GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog ) */
+static jobjectArray
+android_glGetDebugMessageLog__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2
+  (JNIEnv *_env, jobject _this, jint count, jobject sources_ref, jobject types_ref, jobject ids_ref, jobject severities_ref) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return 0;
+}
diff --git a/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.java b/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.java
new file mode 100644
index 0000000..9162c0a
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.java
@@ -0,0 +1,51 @@
+    // C function GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native int glGetDebugMessageLog(
+        int count,
+        int bufSize,
+        int[] sources,
+        int sourcesOffset,
+        int[] types,
+        int typesOffset,
+        int[] ids,
+        int idsOffset,
+        int[] severities,
+        int severitiesOffset,
+        int[] lengths,
+        int lengthsOffset,
+        byte[] messageLog,
+        int messageLogOffset);
+
+    // C function GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native int glGetDebugMessageLog(
+        int count,
+        java.nio.IntBuffer sources,
+        java.nio.IntBuffer types,
+        java.nio.IntBuffer ids,
+        java.nio.IntBuffer severities,
+        java.nio.IntBuffer lengths,
+        java.nio.ByteBuffer messageLog);
+
+    // C function GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native String[] glGetDebugMessageLog(
+        int count,
+        int[] sources,
+        int sourcesOffset,
+        int[] types,
+        int typesOffset,
+        int[] ids,
+        int idsOffset,
+        int[] severities,
+        int severitiesOffset);
+
+    // C function GLuint glGetDebugMessageLog ( GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog )
+
+    public static native String[] glGetDebugMessageLog(
+        int count,
+        java.nio.IntBuffer sources,
+        java.nio.IntBuffer types,
+        java.nio.IntBuffer ids,
+        java.nio.IntBuffer severities);
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.nativeReg
new file mode 100644
index 0000000..fd027e7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetDebugMessageLog.nativeReg
@@ -0,0 +1,4 @@
+{"glGetDebugMessageLog", "(II[II[II[II[II[II[BI)I", (void *) android_glGetDebugMessageLog__II_3II_3II_3II_3II_3II_3BI },
+{"glGetDebugMessageLog", "(ILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)I", (void *) android_glGetDebugMessageLog__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
+{"glGetDebugMessageLog", "(I[II[II[II[II)[Ljava/lang/String;", (void *) android_glGetDebugMessageLog__I_3II_3II_3II_3II },
+{"glGetDebugMessageLog", "(ILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;)[Ljava/lang/String;", (void *) android_glGetDebugMessageLog__ILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2 },
diff --git a/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.cpp b/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.cpp
new file mode 100644
index 0000000..16f03ab
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.cpp
@@ -0,0 +1,7 @@
+/* void glGetObjectLabel ( GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label ) */
+static jstring
+android_glGetObjectLabel(JNIEnv *_env, jobject _this, jint identifier, jint name) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.java b/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.java
new file mode 100644
index 0000000..23eb1bb
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.java
@@ -0,0 +1,4 @@
+    // C function void glGetObjectLabel ( GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label )
+
+    public static native String glGetObjectLabel(int identifier, int name);
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.nativeReg
new file mode 100644
index 0000000..318f07a
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetObjectLabel.nativeReg
@@ -0,0 +1 @@
+{"glGetObjectLabel", "(II)Ljava/lang/String;", (void *) android_glGetObjectLabel },
diff --git a/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.cpp b/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.cpp
new file mode 100644
index 0000000..d73f937
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.cpp
@@ -0,0 +1,7 @@
+/* void glGetObjectPtrLabel ( const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label ) */
+static jstring
+android_glGetObjectPtrLabel(JNIEnv *_env, jobject _this, jlong ptr) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.java b/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.java
new file mode 100644
index 0000000..cdaa0f7
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.java
@@ -0,0 +1,4 @@
+    // C function void glGetObjectPtrLabel ( const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label )
+
+    public static native String glGetObjectPtrLabel(long ptr);
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.nativeReg
new file mode 100644
index 0000000..645b6da
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetObjectPtrLabel.nativeReg
@@ -0,0 +1 @@
+{"glGetObjectPtrLabel", "(J)Ljava/lang/String;", (void *) android_glGetObjectPtrLabel },
diff --git a/opengl/tools/glgen/stubs/gles11/glGetPointerv.cpp b/opengl/tools/glgen/stubs/gles11/glGetPointerv.cpp
new file mode 100644
index 0000000..8311591
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetPointerv.cpp
@@ -0,0 +1,7 @@
+/* void glGetPointerv ( GLenum pname, void **params ) */
+static jlong
+android_glGetPointerv(JNIEnv *_env, jobject _this, jint pname) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+    return NULL;
+}
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetPointerv.java b/opengl/tools/glgen/stubs/gles11/glGetPointerv.java
new file mode 100644
index 0000000..043e5c3
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetPointerv.java
@@ -0,0 +1,6 @@
+    // C function void glGetPointerv ( GLenum pname, void **params )
+
+    public static native long glGetPointerv(
+        int pname
+    );
+
diff --git a/opengl/tools/glgen/stubs/gles11/glGetPointerv.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetPointerv.nativeReg
new file mode 100644
index 0000000..05962f6
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glGetPointerv.nativeReg
@@ -0,0 +1 @@
+{"glGetPointerv", "(I)J", (void *) android_glGetPointerv },
diff --git a/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp b/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp
index d9808ef..55469db 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetShaderSource.cpp
@@ -12,22 +12,18 @@
     jint _sourceRemaining;
     char *source = (char *) 0;
 
-    if (!length_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "length == null";
-        goto exit;
+    if (length_ref) {
+        if (lengthOffset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "lengthOffset < 0";
+            goto exit;
+        }
+        _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+        length_base = (GLsizei *)
+            _env->GetIntArrayElements(length_ref, (jboolean *)0);
+        length = length_base + lengthOffset;
     }
-    if (lengthOffset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "lengthOffset < 0";
-        goto exit;
-    }
-    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
-    length_base = (GLsizei *)
-        _env->GetIntArrayElements(length_ref, (jboolean *)0);
-    length = length_base + lengthOffset;
 
     if (!source_ref) {
         _exception = 1;
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
index cb656c8..aa0d2a4 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.cpp
@@ -18,22 +18,18 @@
     jint _nameRemaining;
     char *name = (char *) 0;
 
-    if (!length_ref) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "length == null";
-        goto exit;
+    if (length_ref) {
+        if (lengthOffset < 0) {
+            _exception = 1;
+            _exceptionType = "java/lang/IllegalArgumentException";
+            _exceptionMessage = "lengthOffset < 0";
+            goto exit;
+        }
+        _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
+        length_base = (GLsizei *)
+            _env->GetIntArrayElements(length_ref, (jboolean *)0);
+        length = length_base + lengthOffset;
     }
-    if (lengthOffset < 0) {
-        _exception = 1;
-        _exceptionType = "java/lang/IllegalArgumentException";
-        _exceptionMessage = "lengthOffset < 0";
-        goto exit;
-    }
-    _lengthRemaining = _env->GetArrayLength(length_ref) - lengthOffset;
-    length_base = (GLsizei *)
-        _env->GetIntArrayElements(length_ref, (jboolean *)0);
-    length = length_base + lengthOffset;
 
     if (!size_ref) {
         _exception = 1;
@@ -122,22 +118,35 @@
 static void
 android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B
   (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jbyte name) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "deprecated");
+}
+
+/* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
+static void
+android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2
+  (JNIEnv *_env, jobject _this, jint program, jint index, jint bufsize, jobject length_buf, jobject size_buf, jobject type_buf, jobject name_buf) {
     jintArray _lengthArray = (jintArray) 0;
     jint _lengthBufferOffset = (jint) 0;
     jintArray _sizeArray = (jintArray) 0;
     jint _sizeBufferOffset = (jint) 0;
     jintArray _typeArray = (jintArray) 0;
     jint _typeBufferOffset = (jint) 0;
+    jbyteArray _nameArray = (jbyteArray)0;
+    jint _nameBufferOffset = (jint)0;
     jint _lengthRemaining;
     GLsizei *length = (GLsizei *) 0;
     jint _sizeRemaining;
     GLint *size = (GLint *) 0;
     jint _typeRemaining;
     GLenum *type = (GLenum *) 0;
+    jint _nameRemaining;
+    GLchar* name = (GLchar*)0;
+
 
     length = (GLsizei *)getPointer(_env, length_buf, (jarray*)&_lengthArray, &_lengthRemaining, &_lengthBufferOffset);
     size = (GLint *)getPointer(_env, size_buf, (jarray*)&_sizeArray, &_sizeRemaining, &_sizeBufferOffset);
     type = (GLenum *)getPointer(_env, type_buf, (jarray*)&_typeArray, &_typeRemaining, &_typeBufferOffset);
+    name = (GLchar*)getPointer(_env, name_buf, (jarray*)&_nameArray, &_nameRemaining, &_nameBufferOffset);
     if (length == NULL) {
         char * _lengthBase = (char *)_env->GetIntArrayElements(_lengthArray, (jboolean *) 0);
         length = (GLsizei *) (_lengthBase + _lengthBufferOffset);
@@ -150,6 +159,10 @@
         char * _typeBase = (char *)_env->GetIntArrayElements(_typeArray, (jboolean *) 0);
         type = (GLenum *) (_typeBase + _typeBufferOffset);
     }
+    if (name == NULL) {
+        char* _nameBase = (char *)_env->GetByteArrayElements(_nameArray, (jboolean*)0);
+        name = (GLchar *) (_nameBase + _nameBufferOffset);
+    }
     glGetTransformFeedbackVarying(
         (GLuint)program,
         (GLuint)index,
@@ -157,11 +170,7 @@
         (GLsizei *)length,
         (GLint *)size,
         (GLenum *)type,
-        // The cast below is incorrect. The driver will end up writing to the
-        // address specified by name, which will always crash the process since
-        // it is guaranteed to be in low memory. The additional static_cast
-        // suppresses the warning for now. http://b/19478262
-        (char *)static_cast<uintptr_t>(name)
+        (GLchar*)name
     );
     if (_typeArray) {
         releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _typeArray, (jint*)type, JNI_TRUE);
@@ -172,6 +181,9 @@
     if (_lengthArray) {
         releaseArrayPointer<jintArray, jint*, IntArrayReleaser>(_env, _lengthArray, (jint*)length, JNI_TRUE);
     }
+    if (_nameArray) {
+        releaseArrayPointer<jbyteArray, jbyte*, ByteArrayReleaser>(_env, _nameArray, (jbyte*)name, JNI_TRUE);
+    }
 }
 
 /* void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name ) */
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java
index f73bbfe..e54359d 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.java
@@ -15,7 +15,10 @@
     );
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
-
+    /**
+     * @deprecated
+     * Use the version that takes a ByteBuffer as the last argument, or the versions that return a String.
+     * */
     public static native void glGetTransformFeedbackVarying(
         int program,
         int index,
@@ -28,6 +31,18 @@
 
     // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
 
+    public static native void glGetTransformFeedbackVarying(
+        int program,
+        int index,
+        int bufsize,
+        java.nio.IntBuffer length,
+        java.nio.IntBuffer size,
+        java.nio.IntBuffer type,
+        java.nio.ByteBuffer name
+    );
+
+    // C function void glGetTransformFeedbackVarying ( GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name )
+
     public static native String glGetTransformFeedbackVarying(
         int program,
         int index,
diff --git a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg
index 412d04c..7f5829b 100644
--- a/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg
+++ b/opengl/tools/glgen/stubs/gles11/glGetTransformFeedbackVarying.nativeReg
@@ -1,4 +1,5 @@
 {"glGetTransformFeedbackVarying", "(III[II[II[II[BI)V", (void *) android_glGetTransformFeedbackVarying__III_3II_3II_3II_3BI },
 {"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;B)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2B },
+{"glGetTransformFeedbackVarying", "(IIILjava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/IntBuffer;Ljava/nio/ByteBuffer;)V", (void *) android_glGetTransformFeedbackVarying__IIILjava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_IntBuffer_2Ljava_nio_ByteBuffer_2 },
 {"glGetTransformFeedbackVarying", "(II[II[II)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying1 },
 {"glGetTransformFeedbackVarying", "(IILjava/nio/IntBuffer;Ljava/nio/IntBuffer;)Ljava/lang/String;", (void *) android_glGetTransformFeedbackVarying2 },
diff --git a/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.cpp b/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.cpp
new file mode 100644
index 0000000..0925b8f
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.cpp
@@ -0,0 +1,6 @@
+/* void glObjectPtrLabel ( const void *ptr, GLsizei length, const GLchar *label ) */
+static void
+android_glObjectPtrLabel(JNIEnv *_env, jobject _this, jlong ptr, jstring label) {
+    jniThrowException(_env, "java/lang/UnsupportedOperationException", "not yet implemented");
+}
+
diff --git a/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.java b/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.java
new file mode 100644
index 0000000..8e96a41
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.java
@@ -0,0 +1,4 @@
+    // C function void glObjectPtrLabel ( const void *ptr, GLsizei length, const GLchar *label )
+
+    public static native void glObjectPtrLabel(long ptr, String label);
+
diff --git a/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.nativeReg b/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.nativeReg
new file mode 100644
index 0000000..0cd9cf8
--- /dev/null
+++ b/opengl/tools/glgen/stubs/gles11/glObjectPtrLabel.nativeReg
@@ -0,0 +1 @@
+{"glObjectPtrLabel", "(JLjava/lang/String;)V", (void *) android_glObjectPtrLabel },
diff --git a/opengl/tools/glgen2/glgen.py b/opengl/tools/glgen2/glgen.py
index 9b30fd1..a140091 100755
--- a/opengl/tools/glgen2/glgen.py
+++ b/opengl/tools/glgen2/glgen.py
@@ -56,35 +56,32 @@
 def nonestr(s):
     return s if s else ""
 
-
-def parseTypedName(elem):
-    type = [nonestr(elem.text)]
+def parseProto(elem):
+    type = nonestr(elem.text)
     name = None
     for subelem in elem:
         text = nonestr(subelem.text)
-        tail = nonestr(subelem.tail)
         if subelem.tag == 'name':
             name = text
-            break
         else:
-            type.extend([text, tail])
-    return (''.join(type).strip(), name)
+            type += text
+            type += nonestr(subelem.tail)
+    return (type.strip(), name)
 
+def parseParam(elem):
+    name = elem.find('name').text
+    declaration = ''.join(elem.itertext())
+    return (name, declaration)
 
-# Format a list of (type, name) tuples as a C-style parameter list
+# Format a list of (type, declaration) tuples as a C-style parameter list
 def fmtParams(params):
     if not params:
         return 'void'
-    return ', '.join(['%s %s' % (p[0], p[1]) for p in params])
-
-# Format a list of (type, name) tuples as a C-style argument list
-def fmtArgs(params):
     return ', '.join(p[1] for p in params)
 
-# Format a list of (type, name) tuples as comma-separated '"type", name'
-def fmtTypeNameList(params):
-    return ', '.join(['"%s", %s' % (p[0], p[1]) for p in params])
-
+# Format a list of (type, declaration) tuples as a C-style argument list
+def fmtArgs(params):
+    return ', '.join(p[0] for p in params)
 
 def overrideSymbolName(sym, apiname):
     # The wrapper intercepts various glGet and glGetString functions and
@@ -122,9 +119,8 @@
     def genCmd(self, cmd, name):
         reg.OutputGenerator.genCmd(self, cmd, name)
 
-        rtype, fname = parseTypedName(cmd.elem.find('proto'))
-        params = [parseTypedName(p) for p in cmd.elem.findall('param')]
-
+        rtype, fname = parseProto(cmd.elem.find('proto'))
+        params = [parseParam(p) for p in cmd.elem.findall('param')]
         call = 'CALL_GL_API' if rtype == 'void' else 'CALL_GL_API_RETURN'
         print('%s API_ENTRY(%s)(%s) {\n'
               '    %s(%s%s%s);\n'
@@ -138,7 +134,7 @@
 
 
 # Collect all API prototypes across all families, remove duplicates,
-# emit to entries.in and trace.in files.
+# emit to entries.in and enums.in files.
 class ApiGenerator(reg.OutputGenerator):
     def __init__(self):
         reg.OutputGenerator.__init__(self, sys.stderr, sys.stderr, None)
@@ -147,8 +143,8 @@
 
     def genCmd(self, cmd, name):
         reg.OutputGenerator.genCmd(self, cmd, name)
-        rtype, fname = parseTypedName(cmd.elem.find('proto'))
-        params = [parseTypedName(p) for p in cmd.elem.findall('param')]
+        rtype, fname = parseProto(cmd.elem.find('proto'))
+        params = [parseParam(p) for p in cmd.elem.findall('param')]
         self.cmds.append({'rtype': rtype, 'name': fname, 'params': params})
 
     def genEnum(self, enuminfo, name):
@@ -199,26 +195,6 @@
                   % (cmd['rtype'], cmd['name'], fmtParams(cmd['params'])),
                   file=outfile)
 
-    # Write traces.in
-    def writeTrace(self, outfile):
-        for cmd in self.cmds:
-            if cmd['rtype'] == 'void':
-                ret = '_VOID('
-            else:
-                ret = '(%s, ' % cmd['rtype']
-
-            params = cmd['params']
-            if len(params) > 0:
-                typeNameList = ', ' + fmtTypeNameList(params)
-            else:
-                typeNameList = ''
-
-            print('TRACE_GL%s%s, (%s), (%s), %d%s)'
-                  % (ret, cmd['name'],
-                     fmtParams(params), fmtArgs(params),
-                     len(params), typeNameList),
-                  file=outfile)
-
     # Write enums.in
     def writeEnums(self, outfile):
         for enum in self.enums.iteritems():
@@ -232,8 +208,8 @@
 
     def genCmd(self, cmd, name):
         reg.OutputGenerator.genCmd(self, cmd, name)
-        rtype, fname = parseTypedName(cmd.elem.find('proto'))
-        params = [parseTypedName(p) for p in cmd.elem.findall('param')]
+        rtype, fname = parseProto(cmd.elem.find('proto'))
+        params = [parseParam(p) for p in cmd.elem.findall('param')]
 
         print('%s %s ( %s )' % (rtype, fname, fmtParams(params)),
               file=self.outFile)
@@ -295,8 +271,6 @@
     apigen.finish()
     with open('../../libs/entries.in', 'w') as f:
         apigen.writeEntries(f)
-    with open('../../libs/trace.in', 'w') as f:
-        apigen.writeTrace(f)
     with open('../../libs/enums.in', 'w') as f:
         apigen.writeEnums(f)
 
@@ -313,7 +287,12 @@
             emitversions        = None,
             defaultExtensions   = None,
             addExtensions       = '^({})$'.format('|'.join(AEP_EXTENSIONS)),
-            filename            = '../glgen/specs/gles11/GLES31Ext.spec')]
+            filename            = '../glgen/specs/gles11/GLES31Ext.spec'),
+        reg.GeneratorOptions(
+            apiname             = 'gles2',
+            profile             = 'common',
+            versions            = '3\.2',
+            filename            = '../glgen/specs/gles11/GLES32.spec')]
     # SpecGenerator creates a good starting point, but the CFunc.java parser is
     # so terrible that the .spec file needs a lot of manual massaging before
     # it works. Commenting this out to avoid accidentally overwriting all the
diff --git a/opengl/tools/glgen2/registry/egl.xml b/opengl/tools/glgen2/registry/egl.xml
index 6f6ebc3..c9384ce 100755
--- a/opengl/tools/glgen2/registry/egl.xml
+++ b/opengl/tools/glgen2/registry/egl.xml
@@ -54,22 +54,27 @@
         <type>typedef unsigned int <name>EGLenum</name>;</type>
         <type requires="khrplatform">typedef intptr_t <name>EGLAttribKHR</name>;</type>
         <type requires="khrplatform">typedef intptr_t <name>EGLAttrib</name>;</type>
+        <type>typedef void *<name>EGLClientBuffer</name>;</type>
         <type>typedef void *<name>EGLConfig</name>;</type>
         <type>typedef void *<name>EGLContext</name>;</type>
+        <type>typedef void *<name>EGLDeviceEXT</name>;</type>
         <type>typedef void *<name>EGLDisplay</name>;</type>
-        <type>typedef void *<name>EGLSurface</name>;</type>
-        <type>typedef void *<name>EGLClientBuffer</name>;</type>
-        <type>typedef void (*<name>__eglMustCastToProperFunctionPointerType</name>)(void);</type>
-        <type>typedef void *<name>EGLImageKHR</name>;</type>
         <type>typedef void *<name>EGLImage</name>;</type>
-        <type>typedef void *<name>EGLSyncKHR</name>;</type>
+        <type>typedef void *<name>EGLImageKHR</name>;</type>
+        <type>typedef void *<name>EGLLabelKHR</name>;</type>
+        <type>typedef void *<name>EGLObjectKHR</name>;</type>
+        <type>typedef void *<name>EGLOutputLayerEXT</name>;</type>
+        <type>typedef void *<name>EGLOutputPortEXT</name>;</type>
+        <type>typedef void *<name>EGLStreamKHR</name>;</type>
+        <type>typedef void *<name>EGLSurface</name>;</type>
         <type>typedef void *<name>EGLSync</name>;</type>
+        <type>typedef void *<name>EGLSyncKHR</name>;</type>
+        <type>typedef void *<name>EGLSyncNV</name>;</type>
+        <type>typedef void (*<name>__eglMustCastToProperFunctionPointerType</name>)(void);</type>
         <type requires="khrplatform">typedef khronos_utime_nanoseconds_t <name>EGLTimeKHR</name>;</type>
         <type requires="khrplatform">typedef khronos_utime_nanoseconds_t <name>EGLTime</name>;</type>
-        <type>typedef void *<name>EGLSyncNV</name>;</type>
         <type requires="khrplatform">typedef khronos_utime_nanoseconds_t <name>EGLTimeNV</name>;</type>
         <type requires="khrplatform">typedef khronos_utime_nanoseconds_t <name>EGLuint64NV</name>;</type>
-        <type>typedef void *<name>EGLStreamKHR</name>;</type>
         <type requires="khrplatform">typedef khronos_uint64_t <name>EGLuint64KHR</name>;</type>
         <type>typedef int <name>EGLNativeFileDescriptorKHR</name>;</type>
         <type requires="khrplatform">typedef khronos_ssize_t <name>EGLsizeiANDROID</name>;</type>
@@ -81,6 +86,7 @@
     EGLint iHeight;
     EGLint iStride;
 };</type>
+        <type>typedef void (<apientry/> *<name>EGLDEBUGPROCKHR</name>)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);</type>
     </types>
 
     <!-- SECTION: EGL enumerant (token) definitions. -->
@@ -172,10 +178,14 @@
         <enum value="-1" name="EGL_NO_NATIVE_FENCE_FD_ANDROID"/>
         <enum value="0" name="EGL_DEPTH_ENCODING_NONE_NV"/>
         <enum value="((EGLContext)0)" name="EGL_NO_CONTEXT"/>
+        <enum value="((EGLDeviceEXT)(0))" name="EGL_NO_DEVICE_EXT"/>
         <enum value="((EGLDisplay)0)" name="EGL_NO_DISPLAY"/>
+        <enum value="((EGLImage)0)" name="EGL_NO_IMAGE"/>
         <enum value="((EGLImageKHR)0)" name="EGL_NO_IMAGE_KHR"/>
         <enum value="((EGLNativeDisplayType)0)" name="EGL_DEFAULT_DISPLAY"/>
         <enum value="((EGLNativeFileDescriptorKHR)(-1))" name="EGL_NO_FILE_DESCRIPTOR_KHR"/>
+        <enum value="((EGLOutputLayerEXT)0)" name="EGL_NO_OUTPUT_LAYER_EXT"/>
+        <enum value="((EGLOutputPortEXT)0)" name="EGL_NO_OUTPUT_PORT_EXT"/>
         <enum value="((EGLStreamKHR)0)" name="EGL_NO_STREAM_KHR"/>
         <enum value="((EGLSurface)0)" name="EGL_NO_SURFACE"/>
         <enum value="((EGLSync)0)" name="EGL_NO_SYNC"/>
@@ -370,6 +380,7 @@
 
     <enums namespace="EGL" start="0x30D0" end="0x30DF" vendor="Symbian" comment="Reserved for Robert Palmer (bug #2545)">
             <unused start="0x30D0" end="0x30D1"/>
+        <enum value="0x30D2" name="EGL_IMAGE_PRESERVED"/>
         <enum value="0x30D2" name="EGL_IMAGE_PRESERVED_KHR"/>
             <unused start="0x30D3" end="0x30D9"/>
         <enum value="0x30DA" name="EGL_SHARED_IMAGE_NOK" comment="Unreleased extension"/>
@@ -453,8 +464,10 @@
             <unused start="0x3137"/>
         <enum value="0x3138" name="EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT"/>
             <unused start="0x3139" end="0x313C"/>
-        <enum value="0x313D" name="EGL_BUFFER_AGE_EXT"/>
+        <enum value="0x313D" name="EGL_BUFFER_AGE_KHR"/>
+        <enum value="0x313D" name="EGL_BUFFER_AGE_EXT" alias="EGL_BUFFER_AGE_KHR"/>
             <unused start="0x313E" end="0x313F"/>
+        <enum value="0x313F" name="EGL_PLATFORM_DEVICE_EXT"/>
     </enums>
 
     <enums namespace="EGL" start="0x3140" end="0x314F" vendor="Google" comment="Reserved for Mathias Agopian (Khronos bug 5199)">
@@ -489,7 +502,8 @@
         <enum value="0x31B0" name="EGL_CONTEXT_OPENGL_DEBUG"/>
         <enum value="0x31B1" name="EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE"/>
         <enum value="0x31B2" name="EGL_CONTEXT_OPENGL_ROBUST_ACCESS"/>
-            <unused start="0x31B3" end="0x31BC" comment="Formerly reserved for EGL_image_stream"/>
+        <enum value="0x31B3" name="EGL_CONTEXT_OPENGL_NO_ERROR_KHR"/>
+            <unused start="0x31B4" end="0x31BC" comment="0x31B3-0x31BC formerly reserved for EGL_image_stream"/>
         <enum value="0x31BD" name="EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR" alias="EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY"/>
         <enum value="0x31BD" name="EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY"/>
         <enum value="0x31BE" name="EGL_NO_RESET_NOTIFICATION"/>
@@ -549,7 +563,8 @@
 
     <enums namespace="EGL" start="0x3200" end="0x320F" vendor="ANGLE" comment="Reserved for Daniel Koch, ANGLE Project (Khronos bug 7139)">
         <enum value="0x3200" name="EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE"/>
-            <unused start="0x3201" end="0x320F"/>
+        <enum value="0x3201" name="EGL_FIXED_SIZE_ANGLE"/>
+            <unused start="0x3202" end="0x320F"/>
     </enums>
 
     <enums namespace="EGL" start="0x3210" end="0x321F" vendor="KHR">
@@ -572,7 +587,39 @@
     </enums>
 
     <enums namespace="EGL" start="0x3220" end="0x325F" vendor="NV" comment="Reserved for Greg Roth (Bug 8220)">
-            <unused start="0x3220" end="0x325F"/>
+            <unused start="0x3220" end="0x322A"/>
+        <enum value="0x322B" name="EGL_BAD_DEVICE_EXT"/>
+        <enum value="0x322C" name="EGL_DEVICE_EXT"/>
+        <enum value="0x322D" name="EGL_BAD_OUTPUT_LAYER_EXT"/>
+        <enum value="0x322E" name="EGL_BAD_OUTPUT_PORT_EXT"/>
+        <enum value="0x322F" name="EGL_SWAP_INTERVAL_EXT"/>
+            <unused start="0x3230" end="0x3232"/>
+        <enum value="0x3233" name="EGL_DRM_DEVICE_FILE_EXT"/>
+        <enum value="0x3234" name="EGL_DRM_CRTC_EXT"/>
+        <enum value="0x3235" name="EGL_DRM_PLANE_EXT"/>
+        <enum value="0x3236" name="EGL_DRM_CONNECTOR_EXT"/>
+        <enum value="0x3237" name="EGL_OPENWF_DEVICE_ID_EXT"/>
+        <enum value="0x3238" name="EGL_OPENWF_PIPELINE_ID_EXT"/>
+        <enum value="0x3239" name="EGL_OPENWF_PORT_ID_EXT"/>
+        <enum value="0x323A" name="EGL_CUDA_DEVICE_NV"/>
+        <enum value="0x323B" name="EGL_CUDA_EVENT_HANDLE_NV"/>
+        <enum value="0x323C" name="EGL_SYNC_CUDA_EVENT_NV"/>
+        <enum value="0x323D" name="EGL_SYNC_CUDA_EVENT_COMPLETE_NV"/>
+            <unused start="0x323E" end="0x324F"/>
+        <enum value="0x3250" name="EGL_MAX_STREAM_METADATA_BLOCKS_NV"/>
+        <enum value="0x3251" name="EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV"/>
+        <enum value="0x3252" name="EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV"/>
+        <enum value="0x3253" name="EGL_PRODUCER_METADATA_NV"/>
+        <enum value="0x3254" name="EGL_CONSUMER_METADATA_NV"/>
+        <enum value="0x3255" name="EGL_METADATA0_SIZE_NV"/>
+        <enum value="0x3256" name="EGL_METADATA1_SIZE_NV"/>
+        <enum value="0x3257" name="EGL_METADATA2_SIZE_NV"/>
+        <enum value="0x3258" name="EGL_METADATA3_SIZE_NV"/>
+        <enum value="0x3259" name="EGL_METADATA0_TYPE_NV"/>
+        <enum value="0x325A" name="EGL_METADATA1_TYPE_NV"/>
+        <enum value="0x325B" name="EGL_METADATA2_TYPE_NV"/>
+        <enum value="0x325C" name="EGL_METADATA3_TYPE_NV"/>
+            <unused start="0x325D" end="0x325F"/>
     </enums>
 
     <enums namespace="EGL" start="0x3260" end="0x326F" vendor="BCOM" comment="Reserved for Gary Sweet, Broadcom (Public bug 620)">
@@ -611,7 +658,9 @@
     </enums>
 
     <enums namespace="EGL" start="0x32A0" end="0x32AF" vendor="Samsung" comment="Reserved for Dongyeon Kim (Public bug 880)">
-            <unused start="0x32A0" end="0x32AF"/>
+        <enum value="0x32A0" name="EGL_NATIVE_BUFFER_TIZEN"/>
+        <enum value="0x32A1" name="EGL_NATIVE_SURFACE_TIZEN"/>
+            <unused start="0x32A2" end="0x32AF"/>
     </enums>
 
     <enums namespace="EGL" start="0x32B0" end="0x32BF" vendor="QCOM" comment="Reserved for Jeff Vigil (Bug 10663) - EGL_QCOM_lock_image spec TBD">
@@ -623,8 +672,85 @@
             <unused start="0x32C1" end="0x32CF"/>
     </enums>
 
-    <enums namespace="EGL" start="0x32D0" end="0x32DF" vendor="QCOM" comment="Reserved for Jeff Vigil (Bug 11735) - EGL_QCOM_gpu_perf spec TBD">
-            <unused start="0x32D0" end="0x32DF"/>
+    <enums namespace="EGL" start="0x32D0" end="0x32EF" vendor="QCOM" comment="Reserved for Jeff Vigil (Bug 11735) - EGL_QCOM_gpu_perf spec TBD + Bug 12286 - EGL_QCOM_content_protection spec TBD">
+            <unused start="0x32D0" end="0x32EF"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x32F0" end="0x32FF" vendor="BCOM" comment="Reserved for Gary Sweet, Broadcom (Bug 12870)">
+            <unused start="0x32F0" end="0x32FF"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x3300" end="0x331F" vendor="QCOM" comment="Reserved for Jeff Vigil (Bugs 12973,12849) - EGL_EXT_yuv_surface spec TBD">
+        <enum value="0x3300" name="EGL_YUV_BUFFER_EXT"/>
+        <enum value="0x3301" name="EGL_YUV_ORDER_EXT"/>
+        <enum value="0x3302" name="EGL_YUV_ORDER_YUV_EXT"/>
+        <enum value="0x3303" name="EGL_YUV_ORDER_YVU_EXT"/>
+        <enum value="0x3304" name="EGL_YUV_ORDER_YUYV_EXT"/>
+        <enum value="0x3305" name="EGL_YUV_ORDER_UYVY_EXT"/>
+        <enum value="0x3306" name="EGL_YUV_ORDER_YVYU_EXT"/>
+        <enum value="0x3307" name="EGL_YUV_ORDER_VYUY_EXT"/>
+        <enum value="0x3308" name="EGL_YUV_ORDER_AYUV_EXT"/>
+            <unused start="0x3309"/>
+        <enum value="0x330A" name="EGL_YUV_CSC_STANDARD_EXT"/>
+        <enum value="0x330B" name="EGL_YUV_CSC_STANDARD_601_EXT"/>
+        <enum value="0x330C" name="EGL_YUV_CSC_STANDARD_709_EXT"/>
+        <enum value="0x330D" name="EGL_YUV_CSC_STANDARD_2020_EXT"/>
+            <unused start="0x330E" end="0x3310"/>
+        <enum value="0x3311" name="EGL_YUV_NUMBER_OF_PLANES_EXT"/>
+        <enum value="0x3312" name="EGL_YUV_SUBSAMPLE_EXT"/>
+        <enum value="0x3313" name="EGL_YUV_SUBSAMPLE_4_2_0_EXT"/>
+        <enum value="0x3314" name="EGL_YUV_SUBSAMPLE_4_2_2_EXT"/>
+        <enum value="0x3315" name="EGL_YUV_SUBSAMPLE_4_4_4_EXT"/>
+            <unused start="0x3316"/>
+        <enum value="0x3317" name="EGL_YUV_DEPTH_RANGE_EXT"/>
+        <enum value="0x3318" name="EGL_YUV_DEPTH_RANGE_LIMITED_EXT"/>
+        <enum value="0x3319" name="EGL_YUV_DEPTH_RANGE_FULL_EXT"/>
+        <enum value="0x331A" name="EGL_YUV_PLANE_BPP_EXT"/>
+        <enum value="0x331B" name="EGL_YUV_PLANE_BPP_0_EXT"/>
+        <enum value="0x331C" name="EGL_YUV_PLANE_BPP_8_EXT"/>
+        <enum value="0x331D" name="EGL_YUV_PLANE_BPP_10_EXT"/>
+            <unused start="0x331E" end="0x331F"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x3320" end="0x339F" vendor="NV" comment="Reserved for James Jones (Bug 13209)">
+            <unused start="0x3320" end="0x3327"/>
+        <enum value="0x3328" name="EGL_PENDING_METADATA_NV"/>
+            <unused start="0x3329" end="0x332B"/>
+        <enum value="0x332C" name="EGL_YUV_PLANE0_TEXTURE_UNIT_NV"/>
+        <enum value="0x332D" name="EGL_YUV_PLANE1_TEXTURE_UNIT_NV"/>
+        <enum value="0x332E" name="EGL_YUV_PLANE2_TEXTURE_UNIT_NV"/>
+            <unused start="0x332F" end="0x339F"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x33A0" end="0x33AF" vendor="ANGLE" comment="Reserved for Shannon Woods (Bug 13175)">
+        <enum value="0x33A0" name="EGL_D3D9_DEVICE_ANGLE"/>
+        <enum value="0x33A1" name="EGL_D3D11_DEVICE_ANGLE"/>
+            <unused start="0x33A2" end="0x33AF"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x33B0" end="0x33BF" vendor="KHR" comment="Reserved for EGL_KHR_debug / Jeff Vigil (Bug 13357)">
+        <enum value="0x33B0" name="EGL_OBJECT_THREAD_KHR"/>
+        <enum value="0x33B1" name="EGL_OBJECT_DISPLAY_KHR"/>
+        <enum value="0x33B2" name="EGL_OBJECT_CONTEXT_KHR"/>
+        <enum value="0x33B3" name="EGL_OBJECT_SURFACE_KHR"/>
+        <enum value="0x33B4" name="EGL_OBJECT_IMAGE_KHR"/>
+        <enum value="0x33B5" name="EGL_OBJECT_SYNC_KHR"/>
+        <enum value="0x33B6" name="EGL_OBJECT_STREAM_KHR"/>
+            <unused start="0x33B7"/>
+        <enum value="0x33B8" name="EGL_DEBUG_CALLBACK_KHR"/>
+        <enum value="0x33B9" name="EGL_DEBUG_MSG_CRITICAL_KHR"/>
+        <enum value="0x33BA" name="EGL_DEBUG_MSG_ERROR_KHR"/>
+        <enum value="0x33BB" name="EGL_DEBUG_MSG_WARN_KHR"/>
+        <enum value="0x33BC" name="EGL_DEBUG_MSG_INFO_KHR"/>
+            <unused start="0x33BD" end="0x33BF"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x33C0" end="0x33DF" vendor="BCOM" comment="Reserved for Gary Sweet (Bug 12203)">
+            <unused start="0x33C0" end="0x33DF"/>
+    </enums>
+
+    <enums namespace="EGL" start="0x33E0" end="0x342F" vendor="QCOM" comment="Reserved for Jeff Vigil (Bugs 10663,13364)">
+            <unused start="0x33E0" end="0x342F"/>
     </enums>
 
 <!-- Please remember that new enumerant allocations must be obtained by
@@ -634,11 +760,10 @@
      Khronos APIs, and new ranges should be allocated with such overlaps in
      mind. -->
 
-<!-- Reservable for future use: 0x32E0-0x3FFF.
-     To generate a new range, allocate multiples of 16 starting at the
-     lowest available point in this block. -->
-    <enums namespace="EGL" start="0x32E0" end="0x3FFF" vendor="KHR">
-            <unused start="0x32E0" end="0x3FFF" comment="Reserved for future use"/>
+<!-- Reservable for future use. To generate a new range, allocate multiples
+     of 16 starting at the lowest available point in this block. -->
+    <enums namespace="EGL" start="0x3420" end="0x3FFF" vendor="KHR">
+            <unused start="0x3420" end="0x3FFF" comment="Reserved for future use"/>
     </enums>
 
     <enums namespace="EGL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with GL.">
@@ -715,6 +840,14 @@
             <param>const <ptype>EGLint</ptype> *<name>attrib_list</name></param>
         </command>
         <command>
+            <proto><ptype>EGLImage</ptype> <name>eglCreateImage</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLContext</ptype> <name>ctx</name></param>
+            <param><ptype>EGLenum</ptype> <name>target</name></param>
+            <param><ptype>EGLClientBuffer</ptype> <name>buffer</name></param>
+            <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLImageKHR</ptype> <name>eglCreateImageKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLContext</ptype> <name>ctx</name></param>
@@ -828,14 +961,25 @@
             <param>const <ptype>EGLint</ptype> *<name>attrib_list</name></param>
         </command>
         <command>
+            <proto><ptype>EGLint</ptype> <name>eglDebugMessageControlKHR</name></proto>
+            <param><ptype>EGLDEBUGPROCKHR</ptype> <name>callback</name></param>
+            <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglDestroyContext</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLContext</ptype> <name>ctx</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglDestroyImage</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLImage</ptype> <name>image</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglDestroyImageKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLImageKHR</ptype> <name>image</name></param>
+            <alias name="eglDestroyImage"/>
         </command>
         <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglDestroyStreamKHR</name></proto>
@@ -868,6 +1012,22 @@
             <param><ptype>EGLSyncKHR</ptype> <name>sync</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglExportDMABUFImageMESA</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLImageKHR</ptype> <name>image</name></param>
+            <param>int *<name>fds</name></param>
+            <param><ptype>EGLint</ptype> *<name>strides</name></param>
+            <param><ptype>EGLint</ptype> *<name>offsets</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglExportDMABUFImageQueryMESA</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLImageKHR</ptype> <name>image</name></param>
+            <param>int *<name>fourcc</name></param>
+            <param>int *<name>num_planes</name></param>
+            <param><ptype>EGLuint64KHR</ptype> *<name>modifiers</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglExportDRMImageMESA</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLImageKHR</ptype> <name>image</name></param>
@@ -911,6 +1071,22 @@
             <proto><ptype>EGLint</ptype> <name>eglGetError</name></proto>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglGetOutputLayersEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param>
+            <param><ptype>EGLOutputLayerEXT</ptype> *<name>layers</name></param>
+            <param><ptype>EGLint</ptype> <name>max_layers</name></param>
+            <param><ptype>EGLint</ptype> *<name>num_layers</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglGetOutputPortsEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param>const <ptype>EGLAttrib</ptype> *<name>attrib_list</name></param>
+            <param><ptype>EGLOutputPortEXT</ptype> *<name>ports</name></param>
+            <param><ptype>EGLint</ptype> <name>max_ports</name></param>
+            <param><ptype>EGLint</ptype> *<name>num_ports</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLDisplay</ptype> <name>eglGetPlatformDisplay</name></proto>
             <param><ptype>EGLenum</ptype> <name>platform</name></param>
             <param>void *<name>native_display</name></param>
@@ -964,6 +1140,13 @@
             <param><ptype>EGLint</ptype> *<name>minor</name></param>
         </command>
         <command>
+            <proto><ptype>EGLint</ptype> <name>eglLabelObjectKHR</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>display</name></param>
+            <param><ptype>EGLenum</ptype> <name>objectType</name></param>
+            <param><ptype>EGLObjectKHR</ptype> <name>object</name></param>
+            <param><ptype>EGLLabelKHR</ptype> <name>label</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglLockSurfaceKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLSurface</ptype> <name>surface</name></param>
@@ -977,6 +1160,20 @@
             <param><ptype>EGLContext</ptype> <name>ctx</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglOutputLayerAttribEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLOutputLayerEXT</ptype> <name>layer</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> <name>value</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglOutputPortAttribEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLOutputPortEXT</ptype> <name>port</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> <name>value</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglPostSubBufferNV</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLSurface</ptype> <name>surface</name></param>
@@ -996,6 +1193,41 @@
             <param><ptype>EGLint</ptype> *<name>value</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryDebugKHR</name></proto>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryDeviceAttribEXT</name></proto>
+            <param><ptype>EGLDeviceEXT</ptype> <name>device</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>const char *<name>eglQueryDeviceStringEXT</name></proto>
+            <param><ptype>EGLDeviceEXT</ptype> <name>device</name></param>
+            <param><ptype>EGLint</ptype> <name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryDevicesEXT</name></proto>
+            <param><ptype>EGLint</ptype> <name>max_devices</name></param>
+            <param><ptype>EGLDeviceEXT</ptype> *<name>devices</name></param>
+            <param><ptype>EGLint</ptype> *<name>num_devices</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryDisplayAttribEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryDisplayAttribNV</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> *<name>value</name></param>
+            <alias name="eglQueryDisplayAttribEXT"/>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglQueryNativeDisplayNV</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLNativeDisplayType</ptype> *<name>display_id</name></param>
@@ -1013,6 +1245,32 @@
             <param><ptype>EGLNativeWindowType</ptype> *<name>window</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryOutputLayerAttribEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLOutputLayerEXT</ptype> <name>layer</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>const char *<name>eglQueryOutputLayerStringEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLOutputLayerEXT</ptype> <name>layer</name></param>
+            <param><ptype>EGLint</ptype> <name>name</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryOutputPortAttribEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLOutputPortEXT</ptype> <name>port</name></param>
+            <param><ptype>EGLint</ptype> <name>attribute</name></param>
+            <param><ptype>EGLAttrib</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>const char *<name>eglQueryOutputPortStringEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLOutputPortEXT</ptype> <name>port</name></param>
+            <param><ptype>EGLint</ptype> <name>name</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglQueryStreamKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
@@ -1020,6 +1278,16 @@
             <param><ptype>EGLint</ptype> *<name>value</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglQueryStreamMetadataNV</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
+            <param><ptype>EGLenum</ptype> <name>name</name></param>
+            <param><ptype>EGLint</ptype> <name>n</name></param>
+            <param><ptype>EGLint</ptype> <name>offset</name></param>
+            <param><ptype>EGLint</ptype> <name>size</name></param>
+            <param>void *<name>data</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglQueryStreamTimeKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
@@ -1075,6 +1343,22 @@
             <param><ptype>EGLGetBlobFuncANDROID</ptype> <name>get</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglSetDamageRegionKHR</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLSurface</ptype> <name>surface</name></param>
+            <param><ptype>EGLint</ptype> *<name>rects</name></param>
+            <param><ptype>EGLint</ptype> <name>n_rects</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglSetStreamMetadataNV</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
+            <param><ptype>EGLint</ptype> <name>n</name></param>
+            <param><ptype>EGLint</ptype> <name>offset</name></param>
+            <param><ptype>EGLint</ptype> <name>size</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglSignalSyncKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLSyncKHR</ptype> <name>sync</name></param>
@@ -1103,6 +1387,18 @@
             <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglStreamConsumerGLTextureExternalAttribsNV</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
+            <param><ptype>EGLAttrib</ptype> <name>*attrib_list</name></param>
+        </command>
+        <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglStreamConsumerOutputEXT</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
+            <param><ptype>EGLOutputLayerEXT</ptype> <name>layer</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglStreamConsumerReleaseKHR</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLStreamKHR</ptype> <name>stream</name></param>
@@ -1127,6 +1423,13 @@
             <param><ptype>EGLint</ptype> <name>n_rects</name></param>
         </command>
         <command>
+            <proto><ptype>EGLBoolean</ptype> <name>eglSwapBuffersWithDamageKHR</name></proto>
+            <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
+            <param><ptype>EGLSurface</ptype> <name>surface</name></param>
+            <param><ptype>EGLint</ptype> *<name>rects</name></param>
+            <param><ptype>EGLint</ptype> <name>n_rects</name></param>
+        </command>
+        <command>
             <proto><ptype>EGLBoolean</ptype> <name>eglSwapBuffersRegionNOK</name></proto>
             <param><ptype>EGLDisplay</ptype> <name>dpy</name></param>
             <param><ptype>EGLSurface</ptype> <name>surface</name></param>
@@ -1424,6 +1727,12 @@
             <enum name="EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z"/>
             <enum name="EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"/>
         </require>
+        <require comment="EGL_KHR_image_base">
+            <enum name="EGL_IMAGE_PRESERVED"/>
+            <enum name="EGL_NO_IMAGE"/>
+            <command name="eglCreateImage"/>
+            <command name="eglDestroyImage"/>
+        </require>
         <require comment="EGL_EXT_platform_base">
             <command name="eglGetPlatformDisplay"/>
             <command name="eglCreatePlatformWindowSurface"/>
@@ -1471,6 +1780,12 @@
                 <enum name="EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE"/>
             </require>
         </extension>
+        <extension name="EGL_ANGLE_device_d3d" supported="egl">
+            <require>
+                <enum name="EGL_D3D9_DEVICE_ANGLE"/>
+                <enum name="EGL_D3D11_DEVICE_ANGLE"/>
+            </require>
+        </extension>
         <extension name="EGL_ANGLE_query_surface_pointer" supported="egl">
             <require>
                 <command name="eglQuerySurfacePointerANGLE"/>
@@ -1481,6 +1796,11 @@
                 <enum name="EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE"/>
             </require>
         </extension>
+        <extension name="EGL_ANGLE_window_fixed_size" supported="egl">
+            <require>
+                <enum name="EGL_FIXED_SIZE_ANGLE"/>
+            </require>
+        </extension>
         <extension name="EGL_ARM_pixmap_multisample_discard" supported="egl">
             <require>
                 <enum name="EGL_DISCARD_SAMPLES_ARM"/>
@@ -1500,6 +1820,42 @@
                 <enum name="EGL_LOSE_CONTEXT_ON_RESET_EXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_device_base" supported="egl">
+            <require>
+                <enum name="EGL_NO_DEVICE_EXT"/>
+                <enum name="EGL_BAD_DEVICE_EXT"/>
+                <enum name="EGL_DEVICE_EXT"/>
+                <command name="eglQueryDeviceAttribEXT"/>
+                <command name="eglQueryDeviceStringEXT"/>
+                <command name="eglQueryDevicesEXT"/>
+                <command name="eglQueryDisplayAttribEXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_device_drm" supported="egl">
+            <require>
+                <enum name="EGL_DRM_DEVICE_FILE_EXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_device_enumeration" supported="egl">
+            <require>
+                <command name="eglQueryDevicesEXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_device_openwf" supported="egl">
+            <require>
+                <enum name="EGL_OPENWF_DEVICE_ID_EXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_device_query" supported="egl">
+            <require>
+                <enum name="EGL_NO_DEVICE_EXT"/>
+                <enum name="EGL_BAD_DEVICE_EXT"/>
+                <enum name="EGL_DEVICE_EXT"/>
+                <command name="eglQueryDeviceAttribEXT"/>
+                <command name="eglQueryDeviceStringEXT"/>
+                <command name="eglQueryDisplayAttribEXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_image_dma_buf_import" supported="egl">
             <require>
                 <enum name="EGL_LINUX_DMA_BUF_EXT"/>
@@ -1531,6 +1887,38 @@
                 <enum name="EGL_MULTIVIEW_VIEW_COUNT_EXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_output_base" supported="egl">
+            <require>
+                <type name="EGLOutputLayerEXT"/>
+                <type name="EGLOutputPortEXT"/>
+                <enum name="EGL_NO_OUTPUT_LAYER_EXT"/>
+                <enum name="EGL_NO_OUTPUT_PORT_EXT"/>
+                <enum name="EGL_BAD_OUTPUT_LAYER_EXT"/>
+                <enum name="EGL_BAD_OUTPUT_PORT_EXT"/>
+                <enum name="EGL_SWAP_INTERVAL_EXT"/>
+                <command name="eglGetOutputLayersEXT"/>
+                <command name="eglGetOutputPortsEXT"/>
+                <command name="eglOutputLayerAttribEXT"/>
+                <command name="eglQueryOutputLayerAttribEXT"/>
+                <command name="eglQueryOutputLayerStringEXT"/>
+                <command name="eglOutputPortAttribEXT"/>
+                <command name="eglQueryOutputPortAttribEXT"/>
+                <command name="eglQueryOutputPortStringEXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_output_drm" supported="egl">
+            <require>
+                <enum name="EGL_DRM_CRTC_EXT"/>
+                <enum name="EGL_DRM_PLANE_EXT"/>
+                <enum name="EGL_DRM_CONNECTOR_EXT"/>
+            </require>
+        </extension>
+        <extension name="EGL_EXT_output_openwf" supported="egl">
+            <require>
+                <enum name="EGL_OPENWF_PIPELINE_ID_EXT"/>
+                <enum name="EGL_OPENWF_PORT_ID_EXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_platform_base" supported="egl">
             <require>
                 <command name="eglGetPlatformDisplayEXT"/>
@@ -1538,6 +1926,11 @@
                 <command name="eglCreatePlatformPixmapSurfaceEXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_platform_device" supported="egl">
+            <require>
+                <enum name="EGL_PLATFORM_DEVICE_EXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_platform_wayland" supported="egl">
             <require>
                 <enum name="EGL_PLATFORM_WAYLAND_EXT"/>
@@ -1554,11 +1947,45 @@
                 <enum name="EGL_PROTECTED_CONTENT_EXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_stream_consumer_egloutput" supported="egl">
+            <require>
+                <command name="eglStreamConsumerOutputEXT"/>
+            </require>
+        </extension>
         <extension name="EGL_EXT_swap_buffers_with_damage" supported="egl">
             <require>
                 <command name="eglSwapBuffersWithDamageEXT"/>
             </require>
         </extension>
+        <extension name="EGL_EXT_yuv_surface" supported="egl">
+            <require>
+                <enum name="EGL_YUV_ORDER_EXT"/>
+                <enum name="EGL_YUV_NUMBER_OF_PLANES_EXT"/>
+                <enum name="EGL_YUV_SUBSAMPLE_EXT"/>
+                <enum name="EGL_YUV_DEPTH_RANGE_EXT"/>
+                <enum name="EGL_YUV_CSC_STANDARD_EXT"/>
+                <enum name="EGL_YUV_PLANE_BPP_EXT"/>
+                <enum name="EGL_YUV_BUFFER_EXT"/>
+                <enum name="EGL_YUV_ORDER_YUV_EXT"/>
+                <enum name="EGL_YUV_ORDER_YVU_EXT"/>
+                <enum name="EGL_YUV_ORDER_YUYV_EXT"/>
+                <enum name="EGL_YUV_ORDER_UYVY_EXT"/>
+                <enum name="EGL_YUV_ORDER_YVYU_EXT"/>
+                <enum name="EGL_YUV_ORDER_VYUY_EXT"/>
+                <enum name="EGL_YUV_ORDER_AYUV_EXT"/>
+                <enum name="EGL_YUV_SUBSAMPLE_4_2_0_EXT"/>
+                <enum name="EGL_YUV_SUBSAMPLE_4_2_2_EXT"/>
+                <enum name="EGL_YUV_SUBSAMPLE_4_4_4_EXT"/>
+                <enum name="EGL_YUV_DEPTH_RANGE_LIMITED_EXT"/>
+                <enum name="EGL_YUV_DEPTH_RANGE_FULL_EXT"/>
+                <enum name="EGL_YUV_CSC_STANDARD_601_EXT"/>
+                <enum name="EGL_YUV_CSC_STANDARD_709_EXT"/>
+                <enum name="EGL_YUV_CSC_STANDARD_2020_EXT"/>
+                <enum name="EGL_YUV_PLANE_BPP_0_EXT"/>
+                <enum name="EGL_YUV_PLANE_BPP_8_EXT"/>
+                <enum name="EGL_YUV_PLANE_BPP_10_EXT"/>
+            </require>
+        </extension>
         <extension name="EGL_HI_clientpixmap" supported="egl">
             <require>
                 <enum name="EGL_CLIENT_PIXMAP_POINTER_HI"/>
@@ -1622,12 +2049,43 @@
                 <enum name="EGL_OPENGL_ES3_BIT_KHR"/>
             </require>
         </extension>
+        <extension name="EGL_KHR_create_context_no_error" supported="egl">
+            <require>
+                <enum name="EGL_CONTEXT_OPENGL_NO_ERROR_KHR"/>
+            </require>
+        </extension>
+        <extension name="EGL_KHR_debug" supported="egl">
+            <require>
+                    <!-- Explicit dependencies require to get EGLDEBUGPROCKHR dependencies correct -->
+                <type name="EGLLabelKHR"/>
+                <type name="EGLObjectKHR"/>
+                <enum name="EGL_OBJECT_THREAD_KHR"/>
+                <enum name="EGL_OBJECT_DISPLAY_KHR"/>
+                <enum name="EGL_OBJECT_CONTEXT_KHR"/>
+                <enum name="EGL_OBJECT_SURFACE_KHR"/>
+                <enum name="EGL_OBJECT_IMAGE_KHR"/>
+                <enum name="EGL_OBJECT_SYNC_KHR"/>
+                <enum name="EGL_OBJECT_STREAM_KHR"/>
+                <enum name="EGL_DEBUG_MSG_CRITICAL_KHR"/>
+                <enum name="EGL_DEBUG_MSG_ERROR_KHR"/>
+                <enum name="EGL_DEBUG_MSG_WARN_KHR"/>
+                <enum name="EGL_DEBUG_MSG_INFO_KHR"/>
+                <enum name="EGL_DEBUG_CALLBACK_KHR"/>
+                <command name="eglDebugMessageControlKHR"/>
+                <command name="eglQueryDebugKHR"/>
+                <command name="eglLabelObjectKHR"/>
+            </require>
+        </extension>
         <extension name="EGL_KHR_fence_sync" protect="KHRONOS_SUPPORT_INT64" supported="egl">
             <require>
-                <!-- @ Most interfaces defined by EGL_KHR_reusable sync -->
+                <!-- Most interfaces also defined by EGL_KHR_reusable sync -->
                 <enum name="EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR"/>
                 <enum name="EGL_SYNC_CONDITION_KHR"/>
                 <enum name="EGL_SYNC_FENCE_KHR"/>
+                <command name="eglCreateSyncKHR"/>
+                <command name="eglDestroySyncKHR"/>
+                <command name="eglClientWaitSyncKHR"/>
+                <command name="eglGetSyncAttribKHR"/>
             </require>
         </extension>
         <extension name="EGL_KHR_get_all_proc_addresses" supported="egl"/>
@@ -1747,6 +2205,12 @@
                 <command name="eglQuerySurface64KHR"/>
             </require>
         </extension>
+        <extension name="EGL_KHR_partial_update" supported="egl">
+            <require>
+                <enum name="EGL_BUFFER_AGE_KHR"/>
+                <command name="eglSetDamageRegionKHR"/>
+            </require>
+        </extension>
         <extension name="EGL_KHR_platform_android" supported="egl">
             <require>
                 <enum name="EGL_PLATFORM_ANDROID_KHR"/>
@@ -1841,6 +2305,11 @@
             </require>
         </extension>
         <extension name="EGL_KHR_surfaceless_context" supported="egl" comment="Just relaxes an error condition"/>
+        <extension name="EGL_KHR_swap_buffers_with_damage" supported="egl">
+            <require>
+                <command name="eglSwapBuffersWithDamageKHR"/>
+            </require>
+        </extension>
         <extension name="EGL_KHR_vg_parent_image" supported="egl">
             <require>
                 <enum name="EGL_VG_PARENT_IMAGE_KHR"/>
@@ -1864,6 +2333,13 @@
                 <command name="eglExportDRMImageMESA"/>
             </require>
         </extension>
+        <extension name="EGL_MESA_image_dma_buf_export" supported="egl">
+            <require>
+                <type name="EGLuint64KHR"/>
+                <command name="eglExportDMABUFImageQueryMESA"/>
+                <command name="eglExportDMABUFImageMESA"/>
+            </require>
+        </extension>
         <extension name="EGL_MESA_platform_gbm" supported="egl">
             <require>
                 <enum name="EGL_PLATFORM_GBM_MESA"/>
@@ -1902,6 +2378,13 @@
                 <enum name="EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV"/>
             </require>
         </extension>
+        <extension name="EGL_NV_cuda_event" supported="egl">
+            <require>
+                <enum name="EGL_CUDA_EVENT_HANDLE_NV"/>
+                <enum name="EGL_SYNC_CUDA_EVENT_NV"/>
+                <enum name="EGL_SYNC_CUDA_EVENT_COMPLETE_NV"/>
+            </require>
+        </extension>
         <extension name="EGL_NV_depth_nonlinear" supported="egl">
             <require>
                 <enum name="EGL_DEPTH_ENCODING_NV"/>
@@ -1909,6 +2392,11 @@
                 <enum name="EGL_DEPTH_ENCODING_NONLINEAR_NV"/>
             </require>
         </extension>
+        <extension name="EGL_NV_device_cuda" supported="egl">
+            <require>
+                <enum name="EGL_CUDA_DEVICE_NV"/>
+            </require>
+        </extension>
         <extension name="EGL_NV_native_query" supported="egl">
             <require>
                 <command name="eglQueryNativeDisplayNV"/>
@@ -1926,6 +2414,37 @@
                 <command name="eglPostSubBufferNV"/>
             </require>
         </extension>
+        <extension name="EGL_NV_stream_consumer_gltexture_yuv" supported="egl">
+            <require>
+                <enum name="EGL_YUV_PLANE0_TEXTURE_UNIT_NV"/>
+                <enum name="EGL_YUV_PLANE1_TEXTURE_UNIT_NV"/>
+                <enum name="EGL_YUV_PLANE2_TEXTURE_UNIT_NV"/>
+                <enum name="EGL_YUV_NUMBER_OF_PLANES_EXT"/>
+                <enum name="EGL_YUV_BUFFER_EXT"/>
+                <command name="eglStreamConsumerGLTextureExternalAttribsNV"/>
+            </require>
+        </extension>
+        <extension name="EGL_NV_stream_metadata" supported="egl">
+            <require>
+                <enum name="EGL_MAX_STREAM_METADATA_BLOCKS_NV"/>
+                <enum name="EGL_MAX_STREAM_METADATA_BLOCK_SIZE_NV"/>
+                <enum name="EGL_MAX_STREAM_METADATA_TOTAL_SIZE_NV"/>
+                <enum name="EGL_PRODUCER_METADATA_NV"/>
+                <enum name="EGL_CONSUMER_METADATA_NV"/>
+                <enum name="EGL_PENDING_METADATA_NV"/>
+                <enum name="EGL_METADATA0_SIZE_NV"/>
+                <enum name="EGL_METADATA1_SIZE_NV"/>
+                <enum name="EGL_METADATA2_SIZE_NV"/>
+                <enum name="EGL_METADATA3_SIZE_NV"/>
+                <enum name="EGL_METADATA0_TYPE_NV"/>
+                <enum name="EGL_METADATA1_TYPE_NV"/>
+                <enum name="EGL_METADATA2_TYPE_NV"/>
+                <enum name="EGL_METADATA3_TYPE_NV"/>
+                <command name="eglQueryDisplayAttribNV"/>
+                <command name="eglSetStreamMetadataNV"/>
+                <command name="eglQueryStreamMetadataNV"/>
+            </require>
+        </extension>
         <extension name="EGL_NV_stream_sync" supported="egl">
             <require>
                 <enum name="EGL_SYNC_TYPE_KHR"/>
@@ -1962,5 +2481,15 @@
                 <command name="eglGetSystemTimeNV"/>
             </require>
         </extension>
+        <extension name="EGL_TIZEN_image_native_buffer" supported="egl">
+            <require>
+                <enum name="EGL_NATIVE_BUFFER_TIZEN"/>
+            </require>
+        </extension>
+        <extension name="EGL_TIZEN_image_native_surface" supported="egl">
+            <require>
+                <enum name="EGL_NATIVE_SURFACE_TIZEN"/>
+            </require>
+        </extension>
     </extensions>
 </registry>
diff --git a/opengl/tools/glgen2/registry/genheaders.py b/opengl/tools/glgen2/registry/genheaders.py
index 78a4a43..fef79ea 100755
--- a/opengl/tools/glgen2/registry/genheaders.py
+++ b/opengl/tools/glgen2/registry/genheaders.py
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 #
-# Copyright (c) 2013-2014 The Khronos Group Inc.
+# Copyright (c) 2013-2015 The Khronos Group Inc.
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and/or associated documentation files (the
@@ -140,7 +140,7 @@
 # Copyright text prefixing all headers (list of strings).
 prefixStrings = [
     '/*',
-    '** Copyright (c) 2013-2014 The Khronos Group Inc.',
+    '** Copyright (c) 2013-2015 The Khronos Group Inc.',
     '**',
     '** Permission is hereby granted, free of charge, to any person obtaining a',
     '** copy of this software and/or associated documentation files (the',
@@ -225,8 +225,8 @@
 gles3PlatformStrings = [ '#include <GLES3/gl3platform.h>', '' ]
 eglPlatformStrings   = [ '#include <EGL/eglplatform.h>', '' ]
 
-# GLES 1/2 extension .h have small addition to calling convention headers
-gles1ExtPlatformStrings = gles2ExtPlatformStrings = [
+# GLES headers have a small addition to calling convention headers for function pointer typedefs
+apiEntryPrefixStrings = [
     '#ifndef GL_APIENTRYP',
     '#define GL_APIENTRYP GL_APIENTRY*',
     '#endif',
@@ -333,7 +333,7 @@
         defaultExtensions = 'gles1',                # Default extensions for GLES 1
         addExtensions     = None,
         removeExtensions  = es1CorePat,             # Remove mandatory ES1 extensions in GLES1/glext.h
-        prefixText        = prefixStrings + gles1ExtPlatformStrings + genDateCommentString,
+        prefixText        = prefixStrings + apiEntryPrefixStrings + genDateCommentString,
         genFuncPointers   = True,
         protectFile       = protectFile,
         protectFeature    = protectFeature,
@@ -342,7 +342,7 @@
         apicall           = 'GL_API ',
         apientry          = 'GL_APIENTRY ',
         apientryp         = 'GL_APIENTRYP '),
-    # GLES 2.0 API - GLES2/gl2.h (no function pointers)
+    # GLES 2.0 API - GLES2/gl2.h (now with function pointers)
     CGeneratorOptions(
         filename          = 'GLES2/gl2.h',
         apiname           = 'gles2',
@@ -352,11 +352,11 @@
         defaultExtensions = None,                   # No default extensions
         addExtensions     = None,
         removeExtensions  = None,
-        prefixText        = prefixStrings + gles2PlatformStrings + genDateCommentString,
-        genFuncPointers   = False,
+        prefixText        = prefixStrings + gles2PlatformStrings + apiEntryPrefixStrings + genDateCommentString,
+        genFuncPointers   = True,
         protectFile       = protectFile,
         protectFeature    = protectFeature,
-        protectProto      = False,                  # Core ES API functions are in the static link libraries
+        protectProto      = protectProto,           # Core ES API functions are in the static link libraries
         protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
         apicall           = 'GL_APICALL ',
         apientry          = 'GL_APIENTRY ',
@@ -371,7 +371,7 @@
         defaultExtensions = 'gles2',                # Default extensions for GLES 2
         addExtensions     = None,
         removeExtensions  = None,
-        prefixText        = prefixStrings + gles2ExtPlatformStrings + genDateCommentString,
+        prefixText        = prefixStrings + apiEntryPrefixStrings + genDateCommentString,
         genFuncPointers   = True,
         protectFile       = protectFile,
         protectFeature    = protectFeature,
@@ -380,7 +380,7 @@
         apicall           = 'GL_APICALL ',
         apientry          = 'GL_APIENTRY ',
         apientryp         = 'GL_APIENTRYP '),
-    # GLES 3.1 API - GLES3/gl31.h (no function pointers)
+    # GLES 3.1 API - GLES3/gl31.h (now with function pointers)
     CGeneratorOptions(
         filename          = 'GLES3/gl31.h',
         apiname           = 'gles2',
@@ -390,16 +390,16 @@
         defaultExtensions = None,                   # No default extensions
         addExtensions     = None,
         removeExtensions  = None,
-        prefixText        = prefixStrings + gles3PlatformStrings + genDateCommentString,
-        genFuncPointers   = False,
+        prefixText        = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + genDateCommentString,
+        genFuncPointers   = True,
         protectFile       = protectFile,
         protectFeature    = protectFeature,
-        protectProto      = False,                  # Core ES API functions are in the static link libraries
+        protectProto      = protectProto,           # Core ES API functions are in the static link libraries
         protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
         apicall           = 'GL_APICALL ',
         apientry          = 'GL_APIENTRY ',
         apientryp         = 'GL_APIENTRYP '),
-    # GLES 3.0 API - GLES3/gl3.h (no function pointers)
+    # GLES 3.0 API - GLES3/gl3.h (now with function pointers)
     CGeneratorOptions(
         filename          = 'GLES3/gl3.h',
         apiname           = 'gles2',
@@ -409,11 +409,11 @@
         defaultExtensions = None,                   # No default extensions
         addExtensions     = None,
         removeExtensions  = None,
-        prefixText        = prefixStrings + gles3PlatformStrings + genDateCommentString,
-        genFuncPointers   = False,
+        prefixText        = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + genDateCommentString,
+        genFuncPointers   = True,
         protectFile       = protectFile,
         protectFeature    = protectFeature,
-        protectProto      = False,                  # Core ES API functions are in the static link libraries
+        protectProto      = protectProto,           # Core ES API functions are in the static link libraries
         protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
         apicall           = 'GL_APICALL ',
         apientry          = 'GL_APIENTRY ',
diff --git a/opengl/tools/glgen2/registry/gl.xml b/opengl/tools/glgen2/registry/gl.xml
index 3f0697a..be231c7 100755
--- a/opengl/tools/glgen2/registry/gl.xml
+++ b/opengl/tools/glgen2/registry/gl.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <registry>
     <comment>
-Copyright (c) 2013-2014 The Khronos Group Inc.
+Copyright (c) 2013-2015 The Khronos Group Inc.
 
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and/or associated documentation files (the
@@ -948,7 +948,6 @@
             <enum name="GL_POST_CONVOLUTION_RED_SCALE_EXT"/>
             <enum name="GL_POST_TEXTURE_FILTER_BIAS_RANGE_SGIX"/>
             <enum name="GL_POST_TEXTURE_FILTER_SCALE_RANGE_SGIX"/>
-            <enum name="GL_PRIMITIVE_BOUNDING_BOX_EXT"/>
             <enum name="GL_PROJECTION_MATRIX"/>
             <enum name="GL_PROJECTION_STACK_DEPTH"/>
             <enum name="GL_READ_BUFFER"/>
@@ -2059,7 +2058,9 @@
         <enum value="0x00000001" name="GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT"/>
         <enum value="0x00000002" name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
         <enum value="0x00000002" name="GL_CONTEXT_FLAG_DEBUG_BIT_KHR"/>
+        <enum value="0x00000004" name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"/>
         <enum value="0x00000004" name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB"/>
+        <enum value="0x00000008" name="GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR"/>
     </enums>
 
     <enums namespace="GL" group="ContextProfileMask" type="bitmask">
@@ -2081,9 +2082,14 @@
         <enum value="0x0020" name="GL_MAP_UNSYNCHRONIZED_BIT"/>
         <enum value="0x0020" name="GL_MAP_UNSYNCHRONIZED_BIT_EXT"/>
         <enum value="0x0040" name="GL_MAP_PERSISTENT_BIT"/>
+        <enum value="0x0040" name="GL_MAP_PERSISTENT_BIT_EXT"/>
         <enum value="0x0080" name="GL_MAP_COHERENT_BIT"/>
+        <enum value="0x0080" name="GL_MAP_COHERENT_BIT_EXT"/>
         <enum value="0x0100" name="GL_DYNAMIC_STORAGE_BIT"/>
+        <enum value="0x0100" name="GL_DYNAMIC_STORAGE_BIT_EXT"/>
         <enum value="0x0200" name="GL_CLIENT_STORAGE_BIT"/>
+        <enum value="0x0200" name="GL_CLIENT_STORAGE_BIT_EXT"/>
+        <enum value="0x0400" name="GL_SPARSE_STORAGE_BIT_ARB"/>
     </enums>
 
     <enums namespace="GL" group="MemoryBarrierMask" type="bitmask">
@@ -2114,6 +2120,7 @@
         <enum value="0x00001000" name="GL_ATOMIC_COUNTER_BARRIER_BIT_EXT"/>
         <enum value="0x00002000" name="GL_SHADER_STORAGE_BARRIER_BIT"/>
         <enum value="0x00004000" name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT"/>
+        <enum value="0x00004000" name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT"/>
         <enum value="0x00008000" name="GL_QUERY_BUFFER_BARRIER_BIT"/>
         <enum value="0xFFFFFFFF" name="GL_ALL_BARRIER_BITS"/>
         <enum value="0xFFFFFFFF" name="GL_ALL_BARRIER_BITS_EXT"/>
@@ -2138,11 +2145,14 @@
         <enum value="0x00000002" name="GL_FRAGMENT_SHADER_BIT"/>
         <enum value="0x00000002" name="GL_FRAGMENT_SHADER_BIT_EXT"/>
         <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT"/>
-        <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT_EXT"/>                             
+        <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT_EXT"/>
+        <enum value="0x00000004" name="GL_GEOMETRY_SHADER_BIT_OES"/>
         <enum value="0x00000008" name="GL_TESS_CONTROL_SHADER_BIT"/>
         <enum value="0x00000008" name="GL_TESS_CONTROL_SHADER_BIT_EXT"/>
+        <enum value="0x00000008" name="GL_TESS_CONTROL_SHADER_BIT_OES"/>
         <enum value="0x00000010" name="GL_TESS_EVALUATION_SHADER_BIT"/>
         <enum value="0x00000010" name="GL_TESS_EVALUATION_SHADER_BIT_EXT"/>
+        <enum value="0x00000010" name="GL_TESS_EVALUATION_SHADER_BIT_OES"/>
         <enum value="0x00000020" name="GL_COMPUTE_SHADER_BIT"/>
         <enum value="0xFFFFFFFF" name="GL_ALL_SHADER_BITS"/>
         <enum value="0xFFFFFFFF" name="GL_ALL_SHADER_BITS_EXT"/>
@@ -2212,6 +2222,7 @@
         <enum value="0x04000000" name="GL_FONT_UNDERLINE_POSITION_BIT_NV"/>
         <enum value="0x08000000" name="GL_FONT_UNDERLINE_THICKNESS_BIT_NV"/>
         <enum value="0x10000000" name="GL_FONT_HAS_KERNING_BIT_NV"/>
+        <enum value="0x20000000" name="GL_FONT_NUM_GLYPH_INDICES_BIT_NV"/>
     </enums>
 
     <enums namespace="GL" group="PerformanceQueryCapsMaskINTEL" type="bitmask">
@@ -2283,10 +2294,26 @@
     <!-- Non-bitmask enums with their own namespace. Generally small numbers
          used for indexed access. -->
 
-    <enums namespace="GL" group="TriangleListSUN" vendor="SUN">
-        <enum value="0x0001" name="GL_RESTART_SUN"/>
-        <enum value="0x0002" name="GL_REPLACE_MIDDLE_SUN"/>
-        <enum value="0x0003" name="GL_REPLACE_OLDEST_SUN"/>
+    <enums namespace="GL" group="CommandOpcodesNV" vendor="NV" comment="For NV_command_list.">
+        <enum value="0x0000" name="GL_TERMINATE_SEQUENCE_COMMAND_NV"/>
+        <enum value="0x0001" name="GL_NOP_COMMAND_NV"/>
+        <enum value="0x0002" name="GL_DRAW_ELEMENTS_COMMAND_NV"/>
+        <enum value="0x0003" name="GL_DRAW_ARRAYS_COMMAND_NV"/>
+        <enum value="0x0004" name="GL_DRAW_ELEMENTS_STRIP_COMMAND_NV"/>
+        <enum value="0x0005" name="GL_DRAW_ARRAYS_STRIP_COMMAND_NV"/>
+        <enum value="0x0006" name="GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV"/>
+        <enum value="0x0007" name="GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV"/>
+        <enum value="0x0008" name="GL_ELEMENT_ADDRESS_COMMAND_NV"/>
+        <enum value="0x0009" name="GL_ATTRIBUTE_ADDRESS_COMMAND_NV"/>
+        <enum value="0x000A" name="GL_UNIFORM_ADDRESS_COMMAND_NV"/>
+        <enum value="0x000B" name="GL_BLEND_COLOR_COMMAND_NV"/>
+        <enum value="0x000C" name="GL_STENCIL_REF_COMMAND_NV"/>
+        <enum value="0x000D" name="GL_LINE_WIDTH_COMMAND_NV"/>
+        <enum value="0x000E" name="GL_POLYGON_OFFSET_COMMAND_NV"/>
+        <enum value="0x000F" name="GL_ALPHA_REF_COMMAND_NV"/>
+        <enum value="0x0010" name="GL_VIEWPORT_COMMAND_NV"/>
+        <enum value="0x0011" name="GL_SCISSOR_COMMAND_NV"/>
+        <enum value="0x0012" name="GL_FRONT_FACE_COMMAND_NV"/>
     </enums>
 
     <enums namespace="GL" group="MapTextureFormatINTEL" vendor="INTEL" comment="Texture memory layouts for INTEL_map_texture">
@@ -2295,14 +2322,6 @@
         <enum value="2" name="GL_LAYOUT_LINEAR_CPU_CACHED_INTEL"/>
     </enums>
 
-    <enums namespace="GL" group="TransformFeedbackTokenNV" vendor="NV" comment="For NV_transform_feedback. No clue why small negative values are used">
-        <enum value="-2" name="GL_NEXT_BUFFER_NV"/>
-        <enum value="-3" name="GL_SKIP_COMPONENTS4_NV"/>
-        <enum value="-4" name="GL_SKIP_COMPONENTS3_NV"/>
-        <enum value="-5" name="GL_SKIP_COMPONENTS2_NV"/>
-        <enum value="-6" name="GL_SKIP_COMPONENTS1_NV"/>
-    </enums>
-
     <enums namespace="GL" group="PathRenderingTokenNV" vendor="NV">
         <enum value="0x00" name="GL_CLOSE_PATH_NV"/>
         <enum value="0x02" name="GL_MOVE_TO_NV"/>
@@ -2329,10 +2348,24 @@
         <enum value="0x17" name="GL_RELATIVE_LARGE_CCW_ARC_TO_NV"/>
         <enum value="0x18" name="GL_LARGE_CW_ARC_TO_NV"/>
         <enum value="0x19" name="GL_RELATIVE_LARGE_CW_ARC_TO_NV"/>
+        <enum value="0x1A" name="GL_CONIC_CURVE_TO_NV"/>
+        <enum value="0x1B" name="GL_RELATIVE_CONIC_CURVE_TO_NV"/>
+            <unused start="0x1C" end="0xBF" comment="Unused for PathRenderingTokenNV"/>
+        <enum value="0xC0" name="GL_SHARED_EDGE_NV"/>
+            <unused start="0xC1" end="0xE7" comment="Unused for PathRenderingTokenNV"/>
+        <enum value="0xE8" name="GL_ROUNDED_RECT_NV"/>
+        <enum value="0xE9" name="GL_RELATIVE_ROUNDED_RECT_NV"/>
+        <enum value="0xEA" name="GL_ROUNDED_RECT2_NV"/>
+        <enum value="0xEB" name="GL_RELATIVE_ROUNDED_RECT2_NV"/>
+        <enum value="0xEC" name="GL_ROUNDED_RECT4_NV"/>
+        <enum value="0xED" name="GL_RELATIVE_ROUNDED_RECT4_NV"/>
+        <enum value="0xEE" name="GL_ROUNDED_RECT8_NV"/>
+        <enum value="0xEF" name="GL_RELATIVE_ROUNDED_RECT8_NV"/>
         <enum value="0xF0" name="GL_RESTART_PATH_NV"/>
         <enum value="0xF2" name="GL_DUP_FIRST_CUBIC_CURVE_TO_NV"/>
         <enum value="0xF4" name="GL_DUP_LAST_CUBIC_CURVE_TO_NV"/>
         <enum value="0xF6" name="GL_RECT_NV"/>
+        <enum value="0xF7" name="GL_RELATIVE_RECT_NV"/>
         <enum value="0xF8" name="GL_CIRCULAR_CCW_ARC_TO_NV"/>
         <enum value="0xFA" name="GL_CIRCULAR_CW_ARC_TO_NV"/>
         <enum value="0xFC" name="GL_CIRCULAR_TANGENT_ARC_TO_NV"/>
@@ -2340,6 +2373,20 @@
         <enum value="0xFF" name="GL_RELATIVE_ARC_TO_NV"/>
     </enums>
 
+    <enums namespace="GL" group="TransformFeedbackTokenNV" vendor="NV" comment="For NV_transform_feedback. No clue why small negative values are used">
+        <enum value="-2" name="GL_NEXT_BUFFER_NV"/>
+        <enum value="-3" name="GL_SKIP_COMPONENTS4_NV"/>
+        <enum value="-4" name="GL_SKIP_COMPONENTS3_NV"/>
+        <enum value="-5" name="GL_SKIP_COMPONENTS2_NV"/>
+        <enum value="-6" name="GL_SKIP_COMPONENTS1_NV"/>
+    </enums>
+
+    <enums namespace="GL" group="TriangleListSUN" vendor="SUN">
+        <enum value="0x0001" name="GL_RESTART_SUN"/>
+        <enum value="0x0002" name="GL_REPLACE_MIDDLE_SUN"/>
+        <enum value="0x0003" name="GL_REPLACE_OLDEST_SUN"/>
+    </enums>
+
     <!-- The default ("API") enum namespace starts here. While some
          assigned values may overlap, and different parts of the
          namespace are reserved for different purposes, it is a single
@@ -2373,23 +2420,29 @@
         <enum value="0x0005" name="GL_TRIANGLE_STRIP"/>
         <enum value="0x0006" name="GL_TRIANGLE_FAN"/>
         <enum value="0x0007" name="GL_QUADS"/>
-        <enum value="0x0007" name="GL_QUADS_EXT"/>                                           
+        <enum value="0x0007" name="GL_QUADS_EXT"/>
+        <enum value="0x0007" name="GL_QUADS_OES"/>
         <enum value="0x0008" name="GL_QUAD_STRIP"/>
         <enum value="0x0009" name="GL_POLYGON"/>
         <enum value="0x000A" name="GL_LINES_ADJACENCY"/>
         <enum value="0x000A" name="GL_LINES_ADJACENCY_ARB"/>
         <enum value="0x000A" name="GL_LINES_ADJACENCY_EXT"/>
+        <enum value="0x000A" name="GL_LINES_ADJACENCY_OES"/>
         <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY"/>
         <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY_ARB"/>
         <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY_EXT"/>
+        <enum value="0x000B" name="GL_LINE_STRIP_ADJACENCY_OES"/>
         <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY"/>
         <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY_ARB"/>
         <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY_EXT"/>
+        <enum value="0x000C" name="GL_TRIANGLES_ADJACENCY_OES"/>
         <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY"/>
         <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY_ARB"/>
         <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY_EXT"/>
+        <enum value="0x000D" name="GL_TRIANGLE_STRIP_ADJACENCY_OES"/>
         <enum value="0x000E" name="GL_PATCHES"/>
-        <enum value="0x000E" name="GL_PATCHES_EXT"/>                                         
+        <enum value="0x000E" name="GL_PATCHES_EXT"/>
+        <enum value="0x000E" name="GL_PATCHES_OES"/>
             <unused start="0x000F" end="0x00FF" comment="Unused for PrimitiveType"/>
         <enum value="0x0100" name="GL_ACCUM"/>
         <enum value="0x0101" name="GL_LOAD"/>
@@ -2415,6 +2468,7 @@
         <enum value="0x0306" name="GL_DST_COLOR"/>
         <enum value="0x0307" name="GL_ONE_MINUS_DST_COLOR"/>
         <enum value="0x0308" name="GL_SRC_ALPHA_SATURATE"/>
+        <enum value="0x0308" name="GL_SRC_ALPHA_SATURATE_EXT"/>
             <unused start="0x0309" end="0x03FF" comment="Unused for BlendingFactor"/>
         <enum value="0x0400" name="GL_FRONT_LEFT"/>
         <enum value="0x0401" name="GL_FRONT_RIGHT"/>
@@ -2441,7 +2495,9 @@
         <enum value="0x0506" name="GL_INVALID_FRAMEBUFFER_OPERATION"/>
         <enum value="0x0506" name="GL_INVALID_FRAMEBUFFER_OPERATION_EXT"/>
         <enum value="0x0506" name="GL_INVALID_FRAMEBUFFER_OPERATION_OES"/>
-            <unused start="0x0507" end="0x05FF" comment="Unused for ErrorCode"/>
+        <enum value="0x0507" name="GL_CONTEXT_LOST"/>
+        <enum value="0x0507" name="GL_CONTEXT_LOST_KHR"/>
+            <unused start="0x0508" end="0x05FF" comment="Unused for ErrorCode"/>
         <enum value="0x0600" name="GL_2D"/>
         <enum value="0x0601" name="GL_3D"/>
         <enum value="0x0602" name="GL_3D_COLOR"/>
@@ -2501,6 +2557,7 @@
         <enum value="0x0B33" name="GL_LIST_INDEX"/>
 
         <enum value="0x0B40" name="GL_POLYGON_MODE"/>
+        <enum value="0x0B40" name="GL_POLYGON_MODE_NV"/>
         <enum value="0x0B41" name="GL_POLYGON_SMOOTH"/>
         <enum value="0x0B42" name="GL_POLYGON_STIPPLE"/>
         <enum value="0x0B43" name="GL_EDGE_FLAG"/>
@@ -2548,11 +2605,15 @@
         <enum value="0x0BA2" name="GL_VIEWPORT"/>
         <enum value="0x0BA3" name="GL_MODELVIEW_STACK_DEPTH"/>
         <enum value="0x0BA3" name="GL_MODELVIEW0_STACK_DEPTH_EXT"/>
+        <enum value="0x0BA3" name="GL_PATH_MODELVIEW_STACK_DEPTH_NV"/>
         <enum value="0x0BA4" name="GL_PROJECTION_STACK_DEPTH"/>
+        <enum value="0x0BA4" name="GL_PATH_PROJECTION_STACK_DEPTH_NV"/>
         <enum value="0x0BA5" name="GL_TEXTURE_STACK_DEPTH"/>
         <enum value="0x0BA6" name="GL_MODELVIEW_MATRIX"/>
         <enum value="0x0BA6" name="GL_MODELVIEW0_MATRIX_EXT"/>
+        <enum value="0x0BA6" name="GL_PATH_MODELVIEW_MATRIX_NV"/>
         <enum value="0x0BA7" name="GL_PROJECTION_MATRIX"/>
+        <enum value="0x0BA7" name="GL_PATH_PROJECTION_MATRIX_NV"/>
         <enum value="0x0BA8" name="GL_TEXTURE_MATRIX"/>
 
         <enum value="0x0BB0" name="GL_ATTRIB_STACK_DEPTH"/>
@@ -2670,12 +2731,15 @@
         <enum value="0x0D32" name="GL_MAX_CLIP_PLANES"/>
         <enum value="0x0D32" name="GL_MAX_CLIP_PLANES_IMG"/>
         <enum value="0x0D32" name="GL_MAX_CLIP_DISTANCES" alias="GL_MAX_CLIP_PLANES"/>
+        <enum value="0x0D32" name="GL_MAX_CLIP_DISTANCES_APPLE"/>
         <enum value="0x0D33" name="GL_MAX_TEXTURE_SIZE"/>
         <enum value="0x0D34" name="GL_MAX_PIXEL_MAP_TABLE"/>
         <enum value="0x0D35" name="GL_MAX_ATTRIB_STACK_DEPTH"/>
         <enum value="0x0D36" name="GL_MAX_MODELVIEW_STACK_DEPTH"/>
+        <enum value="0x0D36" name="GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV"/>
         <enum value="0x0D37" name="GL_MAX_NAME_STACK_DEPTH"/>
         <enum value="0x0D38" name="GL_MAX_PROJECTION_STACK_DEPTH"/>
+        <enum value="0x0D38" name="GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV"/>
         <enum value="0x0D39" name="GL_MAX_TEXTURE_STACK_DEPTH"/>
         <enum value="0x0D3A" name="GL_MAX_VIEWPORT_DIMS"/>
         <enum value="0x0D3B" name="GL_MAX_CLIENT_ATTRIB_STACK_DEPTH"/>
@@ -2738,8 +2802,10 @@
         <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR"/>
         <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR_EXT"/>
         <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR_NV"/>
+        <enum value="0x1004" name="GL_TEXTURE_BORDER_COLOR_OES"/>
         <enum value="0x1005" name="GL_TEXTURE_BORDER"/>
-            <unused start="0x1006" end="0x10FF" comment="Unused for GetTextureParameter"/>
+        <enum value="0x1006" name="GL_TEXTURE_TARGET"/>
+            <unused start="0x1007" end="0x10FF" comment="Unused for GetTextureParameter"/>
         <enum value="0x1100" name="GL_DONT_CARE"/>
         <enum value="0x1101" name="GL_FASTEST"/>
         <enum value="0x1102" name="GL_NICEST"/>
@@ -2766,8 +2832,11 @@
         <enum value="0x1405" name="GL_UNSIGNED_INT"/>
         <enum value="0x1406" name="GL_FLOAT"/>
         <enum value="0x1407" name="GL_2_BYTES"/>
+        <enum value="0x1407" name="GL_2_BYTES_NV"/>
         <enum value="0x1408" name="GL_3_BYTES"/>
+        <enum value="0x1408" name="GL_3_BYTES_NV"/>
         <enum value="0x1409" name="GL_4_BYTES"/>
+        <enum value="0x1409" name="GL_4_BYTES_NV"/>
         <enum value="0x140A" name="GL_DOUBLE"/>
         <enum value="0x140A" name="GL_DOUBLE_EXT"/>
         <enum value="0x140B" name="GL_HALF_FLOAT"/>
@@ -2777,6 +2846,7 @@
         <enum value="0x140C" name="GL_FIXED"/>
         <enum value="0x140C" name="GL_FIXED_OES"/>
             <unused start="0x140D" comment="Leave gap to preserve even/odd int/uint token values"/>
+        <enum value="0x140E" name="GL_INT64_ARB"/>
         <enum value="0x140E" name="GL_INT64_NV"/>
         <enum value="0x140F" name="GL_UNSIGNED_INT64_ARB"/>
         <enum value="0x140F" name="GL_UNSIGNED_INT64_NV"/>
@@ -2807,7 +2877,9 @@
         <enum value="0x1700" name="GL_MODELVIEW"/>
         <enum value="0x1700" name="GL_MODELVIEW0_ARB"/>
         <enum value="0x1700" name="GL_MODELVIEW0_EXT"/>
+        <enum value="0x1700" name="GL_PATH_MODELVIEW_NV"/>
         <enum value="0x1701" name="GL_PROJECTION"/>
+        <enum value="0x1701" name="GL_PATH_PROJECTION_NV"/>
         <enum value="0x1702" name="GL_TEXTURE"/>
             <unused start="0x1703" end="0x17FF" comment="Unused for MatrixMode"/>
         <enum value="0x1800" name="GL_COLOR"/>
@@ -2837,8 +2909,11 @@
         <enum value="0x1A00" name="GL_BITMAP"/>
             <unused start="0x1A01" end="0x1AFF" comment="Unused for PixelType"/>
         <enum value="0x1B00" name="GL_POINT"/>
+        <enum value="0x1B00" name="GL_POINT_NV"/>
         <enum value="0x1B01" name="GL_LINE"/>
+        <enum value="0x1B01" name="GL_LINE_NV"/>
         <enum value="0x1B02" name="GL_FILL"/>
+        <enum value="0x1B02" name="GL_FILL_NV"/>
             <unused start="0x1B03" end="0x1BFF" comment="Unused for PolygonMode"/>
         <enum value="0x1C00" name="GL_RENDER"/>
         <enum value="0x1C01" name="GL_FEEDBACK"/>
@@ -2871,7 +2946,9 @@
         <enum value="0x2300" name="GL_TEXTURE_ENV"/>
             <unused start="0x2301" end="0x23FF" comment="Unused for TextureEnvTarget"/>
         <enum value="0x2400" name="GL_EYE_LINEAR"/>
+        <enum value="0x2400" name="GL_EYE_LINEAR_NV"/>
         <enum value="0x2401" name="GL_OBJECT_LINEAR"/>
+        <enum value="0x2401" name="GL_OBJECT_LINEAR_NV"/>
         <enum value="0x2402" name="GL_SPHERE_MAP"/>
             <unused start="0x2403" end="0x24FF" comment="Unused for TextureGenMode"/>
         <enum value="0x2500" name="GL_TEXTURE_GEN_MODE"/>
@@ -2897,7 +2974,9 @@
             <unused start="0x2902" end="0x29FF" comment="Unused for TextureWrapMode"/>
         <enum value="0x2A00" name="GL_POLYGON_OFFSET_UNITS"/>
         <enum value="0x2A01" name="GL_POLYGON_OFFSET_POINT"/>
+        <enum value="0x2A01" name="GL_POLYGON_OFFSET_POINT_NV"/>
         <enum value="0x2A02" name="GL_POLYGON_OFFSET_LINE"/>
+        <enum value="0x2A02" name="GL_POLYGON_OFFSET_LINE_NV"/>
             <unused start="0x2A03" end="0x2A09" comment="Unused for PolygonOffset"/>
         <enum value="0x2A10" name="GL_R3_G3_B2"/>
             <unused start="0x2A11" end="0x2A1F" comment="Unused for InternalFormat"/>
@@ -2919,23 +2998,31 @@
         <enum value="0x3000" name="GL_CLIP_PLANE0"/>
         <enum value="0x3000" name="GL_CLIP_PLANE0_IMG"/>
         <enum value="0x3000" name="GL_CLIP_DISTANCE0" alias="GL_CLIP_PLANE0"/>
+        <enum value="0x3000" name="GL_CLIP_DISTANCE0_APPLE"/>
         <enum value="0x3001" name="GL_CLIP_PLANE1"/>
         <enum value="0x3001" name="GL_CLIP_PLANE1_IMG"/>
         <enum value="0x3001" name="GL_CLIP_DISTANCE1" alias="GL_CLIP_PLANE1"/>
+        <enum value="0x3001" name="GL_CLIP_DISTANCE1_APPLE"/>
         <enum value="0x3002" name="GL_CLIP_PLANE2"/>
         <enum value="0x3002" name="GL_CLIP_PLANE2_IMG"/>
         <enum value="0x3002" name="GL_CLIP_DISTANCE2" alias="GL_CLIP_PLANE2"/>
+        <enum value="0x3002" name="GL_CLIP_DISTANCE2_APPLE"/>
         <enum value="0x3003" name="GL_CLIP_PLANE3"/>
         <enum value="0x3003" name="GL_CLIP_PLANE3_IMG"/>
         <enum value="0x3003" name="GL_CLIP_DISTANCE3" alias="GL_CLIP_PLANE3"/>
+        <enum value="0x3003" name="GL_CLIP_DISTANCE3_APPLE"/>
         <enum value="0x3004" name="GL_CLIP_PLANE4"/>
         <enum value="0x3004" name="GL_CLIP_PLANE4_IMG"/>
         <enum value="0x3004" name="GL_CLIP_DISTANCE4" alias="GL_CLIP_PLANE4"/>
+        <enum value="0x3004" name="GL_CLIP_DISTANCE4_APPLE"/>
         <enum value="0x3005" name="GL_CLIP_PLANE5"/>
         <enum value="0x3005" name="GL_CLIP_PLANE5_IMG"/>
         <enum value="0x3005" name="GL_CLIP_DISTANCE5" alias="GL_CLIP_PLANE5"/>
+        <enum value="0x3005" name="GL_CLIP_DISTANCE5_APPLE"/>
         <enum value="0x3006" name="GL_CLIP_DISTANCE6"/>
+        <enum value="0x3006" name="GL_CLIP_DISTANCE6_APPLE"/>
         <enum value="0x3007" name="GL_CLIP_DISTANCE7"/>
+        <enum value="0x3007" name="GL_CLIP_DISTANCE7_APPLE"/>
             <unused start="0x3008" end="0x3FFF" comment="Unused for ClipPlaneName"/>
         <enum value="0x4000" name="GL_LIGHT0"/>
         <enum value="0x4001" name="GL_LIGHT1"/>
@@ -2951,9 +3038,7 @@
             <unused start="0x7000" end="0x7FFF" comment="Unused. Do not use."/>
     </enums>
 
-    <enums namespace="GL" start="0x8000" end="0x80BF" vendor="SGI" comment="The primary GL enumerant space begins here. All modern                     enum allocations are in this range. These enums are                     mostly assigned the default class since it's a great                     deal of not very useful work to be more specific"/>
-
-    <enums namespace="GL" vendor="ARB">
+    <enums namespace="GL" start="0x8000" end="0x80BF" vendor="ARB" comment="The primary GL enumerant space begins here. All modern enum allocations are in this range. These enums are mostly assigned the default class since it's a great deal of not very useful work to be more specific">
         <enum value="0x8000" name="GL_ABGR_EXT"/>
         <enum value="0x8001" name="GL_CONSTANT_COLOR"/>
         <enum value="0x8001" name="GL_CONSTANT_COLOR_EXT"/>
@@ -3347,7 +3432,7 @@
     </enums>
 
     <enums namespace="GL" start="0x80C0" end="0x80CF" vendor="ZiiLabs">
-            <unused start="0x80C0" end="0x80C7"/>
+            <unused start="0x80C0" end="0x80C7" vendor="ZiiLabs"/>
         <enum value="0x80C8" name="GL_BLEND_DST_RGB"/>
         <enum value="0x80C8" name="GL_BLEND_DST_RGB_EXT"/>
         <enum value="0x80C8" name="GL_BLEND_DST_RGB_OES"/>
@@ -3424,7 +3509,7 @@
         <enum value="0x80EE" name="GL_PARAMETER_BUFFER_ARB"/>
         <enum value="0x80EF" name="GL_PARAMETER_BUFFER_BINDING_ARB"/>
         <enum value="0x80F0" name="GL_CLIP_VOLUME_CLIPPING_HINT_EXT"/>
-            <unused start="0x80F1" end="0x810F"/>
+            <unused start="0x80F1" end="0x810F" vendor="MS"/>
     </enums>
 
     <enums namespace="GL" start="0x8110" end="0x814F" vendor="SGI">
@@ -3474,6 +3559,7 @@
         <enum value="0x812D" name="GL_CLAMP_TO_BORDER_EXT"/>
         <enum value="0x812D" name="GL_CLAMP_TO_BORDER_NV"/>
         <enum value="0x812D" name="GL_CLAMP_TO_BORDER_SGIS"/>
+        <enum value="0x812D" name="GL_CLAMP_TO_BORDER_OES"/>
         <enum value="0x812E" name="GL_TEXTURE_MULTI_BUFFER_HINT_SGIX"/>
         <enum value="0x812F" name="GL_CLAMP_TO_EDGE"/>
         <enum value="0x812F" name="GL_CLAMP_TO_EDGE_SGIS"/>
@@ -3520,7 +3606,7 @@
         <enum value="0x8150" name="GL_IGNORE_BORDER_HP"/>
         <enum value="0x8151" name="GL_CONSTANT_BORDER"/>
         <enum value="0x8151" name="GL_CONSTANT_BORDER_HP"/>
-            <unused start="0x8152" comment="GL_WRAP_BORDER = 0x8152 was proposed, but not actually promoted to core"/>
+            <unused start="0x8152" vendor="HP" comment="GL_WRAP_BORDER = 0x8152 was proposed, but not actually promoted to core"/>
         <enum value="0x8153" name="GL_REPLICATE_BORDER"/>
         <enum value="0x8153" name="GL_REPLICATE_BORDER_HP"/>
         <enum value="0x8154" name="GL_CONVOLUTION_BORDER_COLOR"/>
@@ -3540,13 +3626,13 @@
         <enum value="0x8161" name="GL_IMAGE_TRANSFORM_2D_HP"/>
         <enum value="0x8162" name="GL_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP"/>
         <enum value="0x8163" name="GL_PROXY_POST_IMAGE_TRANSFORM_COLOR_TABLE_HP"/>
-            <unused start="0x8164"/>
+            <unused start="0x8164" vendor="HP"/>
         <enum value="0x8165" name="GL_OCCLUSION_TEST_HP"/>
         <enum value="0x8166" name="GL_OCCLUSION_TEST_RESULT_HP"/>
         <enum value="0x8167" name="GL_TEXTURE_LIGHTING_MODE_HP"/>
         <enum value="0x8168" name="GL_TEXTURE_POST_SPECULAR_HP"/>
         <enum value="0x8169" name="GL_TEXTURE_PRE_SPECULAR_HP"/>
-            <unused start="0x816A" end="0x816F"/>
+            <unused start="0x816A" end="0x816F" vendor="HP"/>
     </enums>
 
     <enums namespace="GL" start="0x8170" end="0x81CF" vendor="SGI">
@@ -3665,7 +3751,7 @@
     </enums>
 
     <enums namespace="GL" start="0x81D0" end="0x81DF" vendor="SUN">
-            <unused start="0x81D0" end="0x81D1"/>
+            <unused start="0x81D0" end="0x81D1" vendor="SUN"/>
             <unused start="0x81D2" end="0x81D3" comment="No extension spec SUNX_surface_hint"/>
             <!-- <enum value="0x81D2" name="GL_SURFACE_SIZE_HINT_SUNX"/> -->
             <!-- <enum value="0x81D3" name="GL_LARGE_SUNX"/> -->
@@ -3676,7 +3762,7 @@
         <enum value="0x81D8" name="GL_REPLACEMENT_CODE_SUN"/>
         <enum value="0x81D9" name="GL_GLOBAL_ALPHA_SUN"/>
         <enum value="0x81DA" name="GL_GLOBAL_ALPHA_FACTOR_SUN"/>
-            <unused start="0x81DB" end="0x81DF"/>
+            <unused start="0x81DB" end="0x81DF" vendor="SUN"/>
     </enums>
 
     <enums namespace="GL" start="0x81E0" end="0x81FF" vendor="SGI">
@@ -3722,7 +3808,7 @@
 
     <enums namespace="GL" start="0x8200" end="0x820F" vendor="AMD" comment="Range released by MS 2002/9/16">
         <enum value="0x8200" name="GL_TEXT_FRAGMENT_SHADER_ATI"/>
-            <unused start="0x8201" end="0x820F"/>
+            <unused start="0x8201" end="0x820F" vendor="AMD"/>
     </enums>
 
     <enums namespace="GL" start="0x8210" end="0x823F" vendor="ARB">
@@ -3745,11 +3831,14 @@
         <enum value="0x821D" name="GL_NUM_EXTENSIONS"/>
         <enum value="0x821E" name="GL_CONTEXT_FLAGS"/>
         <enum value="0x821F" name="GL_BUFFER_IMMUTABLE_STORAGE"/>
+        <enum value="0x821F" name="GL_BUFFER_IMMUTABLE_STORAGE_EXT"/>
         <enum value="0x8220" name="GL_BUFFER_STORAGE_FLAGS"/>
-        <enum value="0x8221" name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED" comment="Proposed for Bug 10364"/>
+        <enum value="0x8220" name="GL_BUFFER_STORAGE_FLAGS_EXT"/>
+        <enum value="0x8221" name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
+        <enum value="0x8221" name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES"/>
         <enum value="0x8222" name="GL_INDEX"/>
-            <unused start="0x8223" comment="GL_DEPTH_BUFFER = 0x8223 not actually used in the API"/>
-            <unused start="0x8224" comment="GL_STENCIL_BUFFER = 0x8224 not actually used in the API"/>
+            <unused start="0x8223" vendor="ARB" comment="GL_DEPTH_BUFFER = 0x8223 not actually used in the API"/>
+            <unused start="0x8224" vendor="ARB" comment="GL_STENCIL_BUFFER = 0x8224 not actually used in the API"/>
         <enum value="0x8225" name="GL_COMPRESSED_RED"/>
         <enum value="0x8226" name="GL_COMPRESSED_RG"/>
         <enum value="0x8227" name="GL_RG"/>
@@ -3758,9 +3847,11 @@
         <enum value="0x8229" name="GL_R8"/>
         <enum value="0x8229" name="GL_R8_EXT"/>
         <enum value="0x822A" name="GL_R16"/>
+        <enum value="0x822A" name="GL_R16_EXT"/>
         <enum value="0x822B" name="GL_RG8"/>
         <enum value="0x822B" name="GL_RG8_EXT"/>
         <enum value="0x822C" name="GL_RG16"/>
+        <enum value="0x822C" name="GL_RG16_EXT"/>
         <enum value="0x822D" name="GL_R16F"/>
         <enum value="0x822D" name="GL_R16F_EXT"/>
         <enum value="0x822E" name="GL_R32F"/>
@@ -3781,7 +3872,7 @@
         <enum value="0x823A" name="GL_RG16UI"/>
         <enum value="0x823B" name="GL_RG32I"/>
         <enum value="0x823C" name="GL_RG32UI"/>
-            <unused start="0x823D" end="0x823F"/>
+            <unused start="0x823D" end="0x823F" vendor="ARB"/>
     </enums>
 
     <enums namespace="GL" start="0x8240" end="0x82AF" vendor="ARB" comment="Range released by MS on 2002/9/16">
@@ -3835,16 +3926,26 @@
         <enum value="0x8251" name="GL_DEBUG_TYPE_OTHER"/>
         <enum value="0x8251" name="GL_DEBUG_TYPE_OTHER_ARB"/>
         <enum value="0x8251" name="GL_DEBUG_TYPE_OTHER_KHR"/>
+        <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET"/>
         <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET_ARB"/>
         <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET_EXT"/>
+        <enum value="0x8252" name="GL_LOSE_CONTEXT_ON_RESET_KHR"/>
+        <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET"/>
         <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET_ARB"/>
         <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET_EXT"/>
+        <enum value="0x8253" name="GL_GUILTY_CONTEXT_RESET_KHR"/>
+        <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET"/>
         <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET_ARB"/>
         <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET_EXT"/>
+        <enum value="0x8254" name="GL_INNOCENT_CONTEXT_RESET_KHR"/>
+        <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET"/>
         <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET_ARB"/>
         <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET_EXT"/>
+        <enum value="0x8255" name="GL_UNKNOWN_CONTEXT_RESET_KHR"/>
+        <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY"/>
         <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY_ARB"/>
         <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY_EXT"/>
+        <enum value="0x8256" name="GL_RESET_NOTIFICATION_STRATEGY_KHR"/>
         <enum value="0x8257" name="GL_PROGRAM_BINARY_RETRIEVABLE_HINT"/>
         <enum value="0x8258" name="GL_PROGRAM_SEPARABLE"/>
         <enum value="0x8258" name="GL_PROGRAM_SEPARABLE_EXT"/>
@@ -3853,15 +3954,26 @@
         <enum value="0x825A" name="GL_PROGRAM_PIPELINE_BINDING"/>
         <enum value="0x825A" name="GL_PROGRAM_PIPELINE_BINDING_EXT"/>
         <enum value="0x825B" name="GL_MAX_VIEWPORTS"/>
+        <enum value="0x825B" name="GL_MAX_VIEWPORTS_NV"/>
         <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS"/>
+        <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS_EXT"/>
+        <enum value="0x825C" name="GL_VIEWPORT_SUBPIXEL_BITS_NV"/>
         <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE"/>
+        <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE_EXT"/>
+        <enum value="0x825D" name="GL_VIEWPORT_BOUNDS_RANGE_NV"/>
         <enum value="0x825E" name="GL_LAYER_PROVOKING_VERTEX"/>
         <enum value="0x825E" name="GL_LAYER_PROVOKING_VERTEX_EXT"/>
+        <enum value="0x825E" name="GL_LAYER_PROVOKING_VERTEX_OES"/>
         <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX"/>
+        <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_EXT"/>
+        <enum value="0x825F" name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV"/>
         <enum value="0x8260" name="GL_UNDEFINED_VERTEX"/>
-        <enum value="0x8260" name="GL_UNDEFINED_VERTEX_EXT"/>                                
+        <enum value="0x8260" name="GL_UNDEFINED_VERTEX_EXT"/>
+        <enum value="0x8260" name="GL_UNDEFINED_VERTEX_OES"/>
+        <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION"/>
         <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION_ARB"/>
         <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION_EXT"/>
+        <enum value="0x8261" name="GL_NO_RESET_NOTIFICATION_KHR"/>
         <enum value="0x8262" name="GL_MAX_COMPUTE_SHARED_MEMORY_SIZE"/>
         <enum value="0x8263" name="GL_MAX_COMPUTE_UNIFORM_COMPONENTS"/>
         <enum value="0x8264" name="GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS"/>
@@ -3941,7 +4053,7 @@
         <enum value="0x82A8" name="GL_IMAGE_COMPATIBILITY_CLASS"/>
         <enum value="0x82A9" name="GL_IMAGE_PIXEL_FORMAT"/>
         <enum value="0x82AA" name="GL_IMAGE_PIXEL_TYPE"/>
-            <unused start="0x82AB"/>
+            <unused start="0x82AB" vendor="ARB"/>
         <enum value="0x82AC" name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST"/>
         <enum value="0x82AD" name="GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST"/>
         <enum value="0x82AE" name="GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE"/>
@@ -3949,7 +4061,7 @@
     </enums>
 
     <enums namespace="GL" start="0x82B0" end="0x830F" vendor="ARB" comment="Range reclaimed from ADD on 2012/05/10">
-            <unused start="0x82B0"/>
+            <unused start="0x82B0" vendor="ARB"/>
         <enum value="0x82B1" name="GL_TEXTURE_COMPRESSED_BLOCK_WIDTH"/>
         <enum value="0x82B2" name="GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT"/>
         <enum value="0x82B3" name="GL_TEXTURE_COMPRESSED_BLOCK_SIZE"/>
@@ -3993,13 +4105,17 @@
         <enum value="0x82D9" name="GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET"/>
         <enum value="0x82DA" name="GL_MAX_VERTEX_ATTRIB_BINDINGS"/>
         <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL"/>
-        <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL_EXT"/>                          
+        <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL_EXT"/>
+        <enum value="0x82DB" name="GL_TEXTURE_VIEW_MIN_LEVEL_OES"/>
         <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS"/>
-        <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS_EXT"/>                         
+        <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS_EXT"/>
+        <enum value="0x82DC" name="GL_TEXTURE_VIEW_NUM_LEVELS_OES"/>
         <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER"/>
-        <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER_EXT"/>                          
+        <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER_EXT"/>
+        <enum value="0x82DD" name="GL_TEXTURE_VIEW_MIN_LAYER_OES"/>
         <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS"/>
-        <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS_EXT"/>                         
+        <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS_EXT"/>
+        <enum value="0x82DE" name="GL_TEXTURE_VIEW_NUM_LAYERS_OES"/>
         <enum value="0x82DF" name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
         <enum value="0x82E0" name="GL_BUFFER"/>
         <enum value="0x82E0" name="GL_BUFFER_KHR"/>
@@ -4010,6 +4126,7 @@
         <enum value="0x82E3" name="GL_QUERY"/>
         <enum value="0x82E3" name="GL_QUERY_KHR"/>
         <enum value="0x82E4" name="GL_PROGRAM_PIPELINE"/>
+        <enum value="0x82E4" name="GL_PROGRAM_PIPELINE_KHR"/>
         <enum value="0x82E5" name="GL_MAX_VERTEX_ATTRIB_STRIDE"/>
         <enum value="0x82E6" name="GL_SAMPLER"/>
         <enum value="0x82E6" name="GL_SAMPLER_KHR"/>
@@ -4017,7 +4134,31 @@
         <enum value="0x82E8" name="GL_MAX_LABEL_LENGTH"/>
         <enum value="0x82E8" name="GL_MAX_LABEL_LENGTH_KHR"/>
         <enum value="0x82E9" name="GL_NUM_SHADING_LANGUAGE_VERSIONS"/>
-            <unused start="0x82E9" end="0x830F"/>
+        <enum value="0x82EA" name="GL_QUERY_TARGET"/>
+        <!-- 0x82EB = GL_TEXTURE_BINDING was removed in GL 4.5 and
+             ARB_direct_state_access in February 2015 after determining it
+             was not well defined or implementable. -->
+            <unused start="0x82EB" vendor="ARB" comment="Reserved. Formerly used for GL_TEXTURE_BINDING."/>
+        <enum value="0x82EC" name="GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB"/>
+        <enum value="0x82ED" name="GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB"/>
+        <enum value="0x82EE" name="GL_VERTICES_SUBMITTED_ARB"/>
+        <enum value="0x82EF" name="GL_PRIMITIVES_SUBMITTED_ARB"/>
+        <enum value="0x82F0" name="GL_VERTEX_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F1" name="GL_TESS_CONTROL_SHADER_PATCHES_ARB"/>
+        <enum value="0x82F2" name="GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F3" name="GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB"/>
+        <enum value="0x82F4" name="GL_FRAGMENT_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F5" name="GL_COMPUTE_SHADER_INVOCATIONS_ARB"/>
+        <enum value="0x82F6" name="GL_CLIPPING_INPUT_PRIMITIVES_ARB"/>
+        <enum value="0x82F7" name="GL_CLIPPING_OUTPUT_PRIMITIVES_ARB"/>
+        <enum value="0x82F8" name="GL_SPARSE_BUFFER_PAGE_SIZE_ARB"/>
+        <enum value="0x82F9" name="GL_MAX_CULL_DISTANCES"/>
+        <enum value="0x82FA" name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+        <enum value="0x82FB" name="GL_CONTEXT_RELEASE_BEHAVIOR"/>
+        <enum value="0x82FB" name="GL_CONTEXT_RELEASE_BEHAVIOR_KHR"/>
+        <enum value="0x82FC" name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"/>
+        <enum value="0x82FC" name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR"/>
+            <unused start="0x82FD" end="0x830F" vendor="ARB"/>
     </enums>
 
     <enums namespace="GL" start="0x8310" end="0x832F" vendor="SGI">
@@ -4069,7 +4210,7 @@
         <enum value="0x8336" name="GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT"/>
         <enum value="0x8337" name="GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT"/>
         <enum value="0x8338" name="GL_PIXEL_TRANSFORM_2D_MATRIX_EXT"/>
-            <unused start="0x8339" end="0x833F"/>
+            <unused start="0x8339" end="0x833F" vendor="SUN"/>
     </enums>
 
     <enums namespace="GL" start="0x8340" end="0x836F" vendor="SGI">
@@ -4150,10 +4291,12 @@
         <enum value="0x8370" name="GL_MIRRORED_REPEAT_ARB"/>
         <enum value="0x8370" name="GL_MIRRORED_REPEAT_IBM"/>
         <enum value="0x8370" name="GL_MIRRORED_REPEAT_OES"/>
-            <unused start="0x8371" end="0x837F"/>
+            <unused start="0x8371" end="0x837F" vendor="HP"/>
     </enums>
 
-    <enums namespace="GL" start="0x8380" end="0x839F" vendor="IBM"/>
+    <enums namespace="GL" start="0x8380" end="0x839F" vendor="IBM">
+            <unused start="0x8380" end="0x839F" vendor="IBM"/>
+    </enums>
 
     <enums namespace="GL" start="0x83A0" end="0x83BF" vendor="S3">
         <enum value="0x83A0" name="GL_RGB_S3TC"/>
@@ -4162,7 +4305,7 @@
         <enum value="0x83A3" name="GL_RGBA4_S3TC"/>
         <enum value="0x83A4" name="GL_RGBA_DXT5_S3TC"/>
         <enum value="0x83A5" name="GL_RGBA4_DXT5_S3TC"/>
-            <unused start="0x83A6" end="0x83BF"/>
+            <unused start="0x83A6" end="0x83BF" vendor="S3"/>
     </enums>
 
     <enums namespace="GL" start="0x83C0" end="0x83EF" vendor="SGI" comment="Most of this could be reclaimed">
@@ -4178,7 +4321,7 @@
             <!-- <enum value="0x83C8" name="GL_TEXTURE1_SGIS"/> -->
             <!-- <enum value="0x83C9" name="GL_TEXTURE2_SGIS"/> -->
             <!-- <enum value="0x83CA" name="GL_TEXTURE3_SGIS"/> -->
-            <unused start="0x83CB" end="0x83E5"/>
+            <unused start="0x83CB" end="0x83E5" vendor="SGI"/>
             <unused start="0x83E6" end="0x83E9" comment="Incomplete extension SGIX_bali_g_instruments"/>
             <!-- <enum value="0x83E6" name="GL_BALI_NUM_TRIS_CULLED_INSTRUMENT_SGIX"/> -->
             <!-- <enum value="0x83E7" name="GL_BALI_NUM_PRIMS_CLIPPED_INSTRUMENT_SGIX"/> -->
@@ -4211,7 +4354,7 @@
         <enum value="0x83F9" name="GL_PERFQUERY_DONOT_FLUSH_INTEL"/>
         <enum value="0x83FA" name="GL_PERFQUERY_FLUSH_INTEL"/>
         <enum value="0x83FB" name="GL_PERFQUERY_WAIT_INTEL"/>
-            <unused start="0x83FC" end="0x83FE"/>
+            <unused start="0x83FC" end="0x83FE" vendor="INTEL"/>
         <enum value="0x83FF" name="GL_TEXTURE_MEMORY_LAYOUT_INTEL"/>
     </enums>
 
@@ -4236,13 +4379,14 @@
         <enum value="0x8411" name="GL_FRAGMENT_LIGHT5_SGIX"/>
         <enum value="0x8412" name="GL_FRAGMENT_LIGHT6_SGIX"/>
         <enum value="0x8413" name="GL_FRAGMENT_LIGHT7_SGIX"/>
-            <unused start="0x8414" end="0x842B"/>
-        <enum value="0x842C" name="GL_PACK_RESAMPLE_SGIX"/>
-        <enum value="0x842D" name="GL_UNPACK_RESAMPLE_SGIX"/>
-        <enum value="0x842E" name="GL_RESAMPLE_REPLICATE_SGIX"/>
-        <enum value="0x842F" name="GL_RESAMPLE_ZERO_FILL_SGIX"/>
-        <enum value="0x8430" name="GL_RESAMPLE_DECIMATE_SGIX"/>
-            <unused start="0x8431" end="0x8435"/>
+            <unused start="0x8414" end="0x842D" vendor="SGI"/>
+        <enum value="0x842E" name="GL_PACK_RESAMPLE_SGIX" comment="Formerly 0x842C in SGI specfile"/>
+        <enum value="0x842F" name="GL_UNPACK_RESAMPLE_SGIX" comment="Formerly 0x842D in SGI specfile"/>
+        <enum value="0x8430" name="GL_RESAMPLE_DECIMATE_SGIX" comment="Formerly 0x8430 in SGI specfile"/>
+            <unused start="0x8431" end="0x8432" vendor="SGI"/>
+        <enum value="0x8433" name="GL_RESAMPLE_REPLICATE_SGIX" comment="Formerly 0x842E in SGI specfile"/>
+        <enum value="0x8434" name="GL_RESAMPLE_ZERO_FILL_SGIX" comment="Formerly 0x842F in SGI specfile"/>
+            <unused start="0x8435" vendor="SGI"/>
             <!-- Incomplete extension SGIX_fragment_lighting -->
             <!-- <enum value="0x8436"      name="GL_EYE_SPACE_SGIX"/> -->
             <!-- <enum value="0x8437"      name="GL_TANGENT_SPACE_SGIX"/> -->
@@ -4268,7 +4412,7 @@
         <enum value="0x843A" name="GL_BINORMAL_ARRAY_EXT"/>
         <enum value="0x843B" name="GL_CURRENT_TANGENT_EXT"/>
         <enum value="0x843C" name="GL_CURRENT_BINORMAL_EXT"/>
-                     <unused start="0x844D"/>
+            <unused start="0x844D" vendor="SGI"/>
         <enum value="0x843E" name="GL_TANGENT_ARRAY_TYPE_EXT"/>
         <enum value="0x843F" name="GL_TANGENT_ARRAY_STRIDE_EXT"/>
         <enum value="0x8440" name="GL_BINORMAL_ARRAY_TYPE_EXT"/>
@@ -4340,21 +4484,25 @@
             <!-- <enum value="0x8469" name="GL_LUMINANCE16_ICC_SGIX"/> -->
             <!-- <enum value="0x846A" name="GL_INTENSITY16_ICC_SGIX"/> -->
             <!-- <enum value="0x846B" name="GL_LUMINANCE16_ALPHA8_ICC_SGIX"/> -->
-            <unused start="0x846C"/>
+            <unused start="0x846C" vendor="SGI"/>
         <enum value="0x846D" name="GL_ALIASED_POINT_SIZE_RANGE"/>
         <enum value="0x846E" name="GL_ALIASED_LINE_WIDTH_RANGE"/>
-            <unused start="0x846F"/>
+            <unused start="0x846F" vendor="SGI"/>
     </enums>
 
-    <enums namespace="GL" start="0x8470" end="0x848F" vendor="AMD"/>
+    <enums namespace="GL" start="0x8470" end="0x848F" vendor="AMD">
+            <unused start="0x8470" end="0x848F" vendor="AMD"/>
+    </enums>
 
     <enums namespace="GL" start="0x8490" end="0x849F" vendor="REND">
         <enum value="0x8490" name="GL_SCREEN_COORDINATES_REND"/>
         <enum value="0x8491" name="GL_INVERTED_SCREEN_W_REND"/>
-            <unused start="0x8492" end="0x849F"/>
+            <unused start="0x8492" end="0x849F" vendor="REND"/>
     </enums>
 
-    <enums namespace="GL" start="0x84A0" end="0x84BF" vendor="AMD"/>
+    <enums namespace="GL" start="0x84A0" end="0x84BF" vendor="AMD">
+            <unused start="0x84A0" end="0x84BF" vendor="AMD"/>
+    </enums>
 
     <enums namespace="GL" start="0x84C0" end="0x84EF" vendor="ARB">
         <enum value="0x84C0" name="GL_TEXTURE0"/>
@@ -4429,8 +4577,10 @@
         <enum value="0x84E2" name="GL_MAX_TEXTURE_UNITS_ARB"/>
         <enum value="0x84E3" name="GL_TRANSPOSE_MODELVIEW_MATRIX"/>
         <enum value="0x84E3" name="GL_TRANSPOSE_MODELVIEW_MATRIX_ARB"/>
+        <enum value="0x84E3" name="GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV"/>
         <enum value="0x84E4" name="GL_TRANSPOSE_PROJECTION_MATRIX"/>
         <enum value="0x84E4" name="GL_TRANSPOSE_PROJECTION_MATRIX_ARB"/>
+        <enum value="0x84E4" name="GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV"/>
         <enum value="0x84E5" name="GL_TRANSPOSE_TEXTURE_MATRIX"/>
         <enum value="0x84E5" name="GL_TRANSPOSE_TEXTURE_MATRIX_ARB"/>
         <enum value="0x84E6" name="GL_TRANSPOSE_COLOR_MATRIX"/>
@@ -4482,7 +4632,7 @@
         <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8_EXT"/>
         <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8_NV"/>
         <enum value="0x84FA" name="GL_UNSIGNED_INT_24_8_OES"/>
-            <unused start="0x84FB" end="0x84FC"/>
+            <unused start="0x84FB" end="0x84FC" vendor="NV"/>
         <enum value="0x84FD" name="GL_MAX_TEXTURE_LOD_BIAS"/>
         <enum value="0x84FD" name="GL_MAX_TEXTURE_LOD_BIAS_EXT"/>
         <enum value="0x84FE" name="GL_TEXTURE_MAX_ANISOTROPY_EXT"/>
@@ -4643,7 +4793,7 @@
         <enum value="0x8566" name="GL_BLUE_MAX_CLAMP_INGR"/>
         <enum value="0x8567" name="GL_ALPHA_MAX_CLAMP_INGR"/>
         <enum value="0x8568" name="GL_INTERLACE_READ_INGR"/>
-            <unused start="0x8569" end="0x856F"/>
+            <unused start="0x8569" end="0x856F" vendor="ZiiLabs"/>
     </enums>
 
     <enums namespace="GL" start="0x8570" end="0x859F" group="RegisterCombinerPname" vendor="AMD/NV">
@@ -4668,6 +4818,7 @@
         <enum value="0x8576" name="GL_CONSTANT"/>
         <enum value="0x8576" name="GL_CONSTANT_ARB"/>
         <enum value="0x8576" name="GL_CONSTANT_EXT"/>
+        <enum value="0x8576" name="GL_CONSTANT_NV"/>
         <enum value="0x8577" name="GL_PRIMARY_COLOR"/>
         <enum value="0x8577" name="GL_PRIMARY_COLOR_ARB"/>
         <enum value="0x8577" name="GL_PRIMARY_COLOR_EXT"/>
@@ -4697,6 +4848,7 @@
         <enum value="0x8589" name="GL_SOURCE1_ALPHA_ARB"/>
         <enum value="0x8589" name="GL_SOURCE1_ALPHA_EXT"/>
         <enum value="0x8589" name="GL_SRC1_ALPHA" alias="GL_SOURCE1_ALPHA"/>
+        <enum value="0x8589" name="GL_SRC1_ALPHA_EXT"/>
         <enum value="0x858A" name="GL_SOURCE2_ALPHA"/>
         <enum value="0x858A" name="GL_SOURCE2_ALPHA_ARB"/>
         <enum value="0x858A" name="GL_SOURCE2_ALPHA_EXT"/>
@@ -4756,7 +4908,7 @@
         <enum value="0x85B5" name="GL_VERTEX_ARRAY_BINDING"/>
         <enum value="0x85B5" name="GL_VERTEX_ARRAY_BINDING_APPLE"/>
         <enum value="0x85B5" name="GL_VERTEX_ARRAY_BINDING_OES"/>
-            <unused start="0x85B6" comment="Unknown extension (Khronos bug 632)"/>
+            <unused start="0x85B6" vendor="APPLE" comment="Unknown extension (Khronos bug 632)"/>
             <!-- <enum value="0x85B6" name="GL_TEXTURE_MINIMIZE_STORAGE_APPLE"/> -->
         <enum value="0x85B7" name="GL_TEXTURE_RANGE_LENGTH_APPLE"/>
         <enum value="0x85B8" name="GL_TEXTURE_RANGE_POINTER_APPLE"/>
@@ -4785,14 +4937,14 @@
         <enum value="0x85CA" name="GL_R1UI_T2F_N3F_V3F_SUN"/>
         <enum value="0x85CB" name="GL_R1UI_T2F_C4F_N3F_V3F_SUN"/>
         <enum value="0x85CC" name="GL_SLICE_ACCUM_SUN"/>
-            <unused start="0x85CD" end="0x85CF"/>
+            <unused start="0x85CD" end="0x85CF" vendor="SUN"/>
     </enums>
 
     <enums namespace="GL" start="0x85D0" end="0x85DF" vendor="ZiiLabs" comment="3Dlabs private extension for Autodesk">
             <unused start="0x85D0" end="0x85D1" comment="Unknown 3Dlabs private extension for Autodesk (but we know the enum values)"/>
             <!-- <enum value="0x85D0" name="GL_FACET_NORMAL_AUTODESK"/> -->
             <!-- <enum value="0x85D1" name="GL_FACET_NORMAL_ARRAY_AUTODESK"/> -->
-            <unused start="0x85D2" end="0x85DF"/>
+            <unused start="0x85D2" end="0x85DF" vendor="ZiiLabs"/>
     </enums>
 
     <enums namespace="GL" start="0x85E0" end="0x85FF" vendor="SGI">
@@ -4825,14 +4977,14 @@
             <!-- <enum value="0x85F9" name="GL_MAX_LUMINANCE_SGIS"/> -->
             <!-- <enum value="0x85FA" name="GL_MIN_INTENSITY_SGIS"/> -->
             <!-- <enum value="0x85FB" name="GL_MAX_INTENSITY_SGIS"/> -->
-            <unused start="0x85FC" end="0x85FF"/>
+            <unused start="0x85FC" end="0x85FF" vendor="SGI"/>
     </enums>
 
     <enums namespace="GL" start="0x8600" end="0x861F" vendor="SUN">
-            <unused start="0x8600" end="0x8613"/>
+            <unused start="0x8600" end="0x8613" vendor="SUN"/>
         <enum value="0x8614" name="GL_QUAD_MESH_SUN"/>
         <enum value="0x8615" name="GL_TRIANGLE_MESH_SUN"/>
-            <unused start="0x8614" end="0x861F"/>
+            <unused start="0x8614" end="0x861F" vendor="SUN"/>
     </enums>
 
     <enums namespace="GL" start="0x8620" end="0x867F" vendor="NV">
@@ -4963,7 +5115,9 @@
         <enum value="0x867F" name="GL_MAP2_VERTEX_ATTRIB15_4_NV"/>
     </enums>
 
-    <enums namespace="GL" start="0x8680" end="0x869F" vendor="Pixelfusion"/>
+    <enums namespace="GL" start="0x8680" end="0x869F" vendor="Pixelfusion">
+            <unused start="0x8680" end="0x869F" vendor="Pixelfusion"/>
+    </enums>
 
     <enums namespace="GL" start="0x86A0" end="0x86AF" vendor="ARB">
         <enum value="0x86A0" name="GL_TEXTURE_COMPRESSED_IMAGE_SIZE"/>
@@ -5003,7 +5157,7 @@
         <enum value="0x86B2" name="GL_MULTISAMPLE_3DFX"/>
         <enum value="0x86B3" name="GL_SAMPLE_BUFFERS_3DFX"/>
         <enum value="0x86B4" name="GL_SAMPLES_3DFX"/>
-            <unused start="0x86B5" end="0x86BF"/>
+            <unused start="0x86B5" end="0x86BF" vendor="3DFX"/>
     </enums>
 
     <enums namespace="GL" start="0x86C0" end="0x871F" vendor="NV">
@@ -5156,7 +5310,7 @@
         <enum value="0x8744" name="GL_MODULATE_ADD_ATI"/>
         <enum value="0x8745" name="GL_MODULATE_SIGNED_ADD_ATI"/>
         <enum value="0x8746" name="GL_MODULATE_SUBTRACT_ATI"/>
-            <unused start="0x8747" end="0x8749"/>
+            <unused start="0x8747" end="0x8749" vendor="AMD"/>
         <enum value="0x874A" name="GL_SET_AMD"/>
         <enum value="0x874B" name="GL_REPLACE_VALUE_AMD"/>
         <enum value="0x874C" name="GL_STENCIL_OP_VALUE_AMD"/>
@@ -5184,7 +5338,7 @@
         <enum value="0x875C" name="GL_PROXY_TEXTURE_2D_STACK_MESAX"/>
         <enum value="0x875D" name="GL_TEXTURE_1D_STACK_BINDING_MESAX"/>
         <enum value="0x875E" name="GL_TEXTURE_2D_STACK_BINDING_MESAX"/>
-            <unused start="0x875F"/>
+            <unused start="0x875F" vendor="MESA"/>
     </enums>
 
     <enums namespace="GL" start="0x8760" end="0x883F" vendor="AMD">
@@ -5221,7 +5375,7 @@
         <enum value="0x877A" name="GL_DU8DV8_ATI"/>
         <enum value="0x877B" name="GL_BUMP_ENVMAP_ATI"/>
         <enum value="0x877C" name="GL_BUMP_TARGET_ATI"/>
-            <unused start="0x877D" end="0x877F"/>
+            <unused start="0x877D" end="0x877F" vendor="AMD"/>
         <enum value="0x8780" name="GL_VERTEX_SHADER_EXT"/>
         <enum value="0x8781" name="GL_VERTEX_SHADER_BINDING_EXT"/>
         <enum value="0x8782" name="GL_OP_INDEX_EXT"/>
@@ -5372,7 +5526,7 @@
         <enum value="0x880E" name="GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB"/>
         <enum value="0x880F" name="GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB"/>
         <enum value="0x8810" name="GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB"/>
-            <unused start="0x8811" end="0x8813"/>
+            <unused start="0x8811" end="0x8813" vendor="AMD"/>
         <enum value="0x8814" name="GL_RGBA32F"/>
         <enum value="0x8814" name="GL_RGBA32F_ARB"/>
         <enum value="0x8814" name="GL_RGBA32F_EXT"/>
@@ -5426,7 +5580,7 @@
             <!-- RGBA_FLOAT_MODE_ARB equivalent to TYPE_RGBA_FLOAT_ATI -->
         <enum value="0x8820" name="GL_RGBA_FLOAT_MODE_ARB"/>
         <enum value="0x8820" name="GL_RGBA_FLOAT_MODE_ATI"/>
-            <unused start="0x8821" end="0x8822"/>
+            <unused start="0x8821" end="0x8822" vendor="AMD"/>
         <enum value="0x8823" name="GL_WRITEONLY_RENDERING_QCOM"/>
         <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS"/>
         <enum value="0x8824" name="GL_MAX_DRAW_BUFFERS_ARB"/>
@@ -5514,13 +5668,13 @@
         <enum value="0x8834" name="GL_DRAW_BUFFER15_EXT"/>
         <enum value="0x8834" name="GL_DRAW_BUFFER15_NV"/>
         <enum value="0x8835" name="GL_COLOR_CLEAR_UNCLAMPED_VALUE_ATI"/>
-            <unused start="0x8836"/>
+            <unused start="0x8836" vendor="AMD"/>
         <enum value="0x8837" name="GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI" comment="Defined by Mesa but not ATI"/>
-            <unused start="0x8838" end="0x883C"/>
+            <unused start="0x8838" end="0x883C" vendor="AMD"/>
         <enum value="0x883D" name="GL_BLEND_EQUATION_ALPHA"/>
         <enum value="0x883D" name="GL_BLEND_EQUATION_ALPHA_EXT"/>
         <enum value="0x883D" name="GL_BLEND_EQUATION_ALPHA_OES"/>
-            <unused start="0x883E"/>
+            <unused start="0x883E" vendor="AMD"/>
         <enum value="0x883F" name="GL_SUBSAMPLE_DISTANCE_AMD"/>
     </enums>
 
@@ -5609,11 +5763,13 @@
         <enum value="0x8869" name="GL_MAX_VERTEX_ATTRIBS_ARB"/>
         <enum value="0x886A" name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED"/>
         <enum value="0x886A" name="GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB"/>
-            <unused start="0x886B"/>
+            <unused start="0x886B" vendor="NV"/>
         <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"/>
-        <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT"/>               
+        <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT"/>
+        <enum value="0x886C" name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES"/>
         <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"/>
-        <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT"/>            
+        <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT"/>
+        <enum value="0x886D" name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES"/>
         <enum value="0x886E" name="GL_DEPTH_STENCIL_TO_RGBA_NV"/>
         <enum value="0x886F" name="GL_DEPTH_STENCIL_TO_BGRA_NV"/>
         <enum value="0x8870" name="GL_FRAGMENT_PROGRAM_NV"/>
@@ -5628,16 +5784,17 @@
         <enum value="0x8874" name="GL_PROGRAM_ERROR_STRING_NV"/>
         <enum value="0x8875" name="GL_PROGRAM_FORMAT_ASCII_ARB"/>
         <enum value="0x8876" name="GL_PROGRAM_FORMAT_ARB"/>
-            <unused start="0x8877" comment="Should have been assigned to PROGRAM_BINDING_ARB"/>
+            <unused start="0x8877" vendor="NV" comment="Should have been assigned to PROGRAM_BINDING_ARB"/>
         <enum value="0x8878" name="GL_WRITE_PIXEL_DATA_RANGE_NV"/>
         <enum value="0x8879" name="GL_READ_PIXEL_DATA_RANGE_NV"/>
         <enum value="0x887A" name="GL_WRITE_PIXEL_DATA_RANGE_LENGTH_NV"/>
         <enum value="0x887B" name="GL_READ_PIXEL_DATA_RANGE_LENGTH_NV"/>
         <enum value="0x887C" name="GL_WRITE_PIXEL_DATA_RANGE_POINTER_NV"/>
         <enum value="0x887D" name="GL_READ_PIXEL_DATA_RANGE_POINTER_NV"/>
-            <unused start="0x887E"/>
+            <unused start="0x887E" vendor="NV"/>
         <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
-        <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS_EXT"/>                     
+        <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS_EXT"/>
+        <enum value="0x887F" name="GL_GEOMETRY_SHADER_INVOCATIONS_OES"/>
         <enum value="0x8880" name="GL_FLOAT_R_NV"/>
         <enum value="0x8881" name="GL_FLOAT_RG_NV"/>
         <enum value="0x8882" name="GL_FLOAT_RGB_NV"/>
@@ -5767,14 +5924,14 @@
         <enum value="0x88E1" name="GL_STREAM_READ_ARB"/>
         <enum value="0x88E2" name="GL_STREAM_COPY"/>
         <enum value="0x88E2" name="GL_STREAM_COPY_ARB"/>
-            <unused start="0x88E3" comment="To extend ARB_vbo"/>
+            <unused start="0x88E3" vendor="NV" comment="To extend ARB_vbo"/>
         <enum value="0x88E4" name="GL_STATIC_DRAW"/>
         <enum value="0x88E4" name="GL_STATIC_DRAW_ARB"/>
         <enum value="0x88E5" name="GL_STATIC_READ"/>
         <enum value="0x88E5" name="GL_STATIC_READ_ARB"/>
         <enum value="0x88E6" name="GL_STATIC_COPY"/>
         <enum value="0x88E6" name="GL_STATIC_COPY_ARB"/>
-            <unused start="0x88E7" comment="To extend ARB_vbo"/>
+            <unused start="0x88E7" vendor="NV" comment="To extend ARB_vbo"/>
         <enum value="0x88E8" name="GL_DYNAMIC_DRAW"/>
         <enum value="0x88E8" name="GL_DYNAMIC_DRAW_ARB"/>
         <enum value="0x88E9" name="GL_DYNAMIC_READ"/>
@@ -5807,9 +5964,13 @@
         <enum value="0x88F7" name="GL_MAX_PROGRAM_LOOP_DEPTH_NV"/>
         <enum value="0x88F8" name="GL_MAX_PROGRAM_LOOP_COUNT_NV"/>
         <enum value="0x88F9" name="GL_SRC1_COLOR"/>
+        <enum value="0x88F9" name="GL_SRC1_COLOR_EXT"/>
         <enum value="0x88FA" name="GL_ONE_MINUS_SRC1_COLOR"/>
+        <enum value="0x88FA" name="GL_ONE_MINUS_SRC1_COLOR_EXT"/>
         <enum value="0x88FB" name="GL_ONE_MINUS_SRC1_ALPHA"/>
+        <enum value="0x88FB" name="GL_ONE_MINUS_SRC1_ALPHA_EXT"/>
         <enum value="0x88FC" name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS"/>
+        <enum value="0x88FC" name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT"/>
         <enum value="0x88FD" name="GL_VERTEX_ATTRIB_ARRAY_INTEGER"/>
         <enum value="0x88FD" name="GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT"/>
         <enum value="0x88FD" name="GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV"/>
@@ -5833,16 +5994,19 @@
         <enum value="0x8910" name="GL_STENCIL_TEST_TWO_SIDE_EXT"/>
         <enum value="0x8911" name="GL_ACTIVE_STENCIL_FACE_EXT"/>
         <enum value="0x8912" name="GL_MIRROR_CLAMP_TO_BORDER_EXT"/>
-            <unused start="0x8913"/>
+            <unused start="0x8913" vendor="NV"/>
         <enum value="0x8914" name="GL_SAMPLES_PASSED"/>
         <enum value="0x8914" name="GL_SAMPLES_PASSED_ARB"/>
-            <unused start="0x8915"/>
+            <unused start="0x8915" vendor="NV"/>
         <enum value="0x8916" name="GL_GEOMETRY_VERTICES_OUT"/>
-        <enum value="0x8916" name="GL_GEOMETRY_LINKED_VERTICES_OUT_EXT"/>                           
+        <enum value="0x8916" name="GL_GEOMETRY_LINKED_VERTICES_OUT_EXT"/>
+        <enum value="0x8916" name="GL_GEOMETRY_LINKED_VERTICES_OUT_OES"/>
         <enum value="0x8917" name="GL_GEOMETRY_INPUT_TYPE"/>
-        <enum value="0x8917" name="GL_GEOMETRY_LINKED_INPUT_TYPE_EXT"/>                             
+        <enum value="0x8917" name="GL_GEOMETRY_LINKED_INPUT_TYPE_EXT"/>
+        <enum value="0x8917" name="GL_GEOMETRY_LINKED_INPUT_TYPE_OES"/>
         <enum value="0x8918" name="GL_GEOMETRY_OUTPUT_TYPE"/>
-        <enum value="0x8918" name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT"/>                            
+        <enum value="0x8918" name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT"/>
+        <enum value="0x8918" name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES"/>
         <enum value="0x8919" name="GL_SAMPLER_BINDING"/>
         <enum value="0x891A" name="GL_CLAMP_VERTEX_COLOR"/>
         <enum value="0x891A" name="GL_CLAMP_VERTEX_COLOR_ARB"/>
@@ -5948,7 +6112,7 @@
         <enum value="0x8979" name="GL_SWIZZLE_STQ_DQ_ATI"/>
         <enum value="0x897A" name="GL_SWIZZLE_STRQ_ATI"/>
         <enum value="0x897B" name="GL_SWIZZLE_STRQ_DQ_ATI"/>
-            <unused start="0x897C" end="0x897F"/>
+            <unused start="0x897C" end="0x897F" vendor="AMD"/>
     </enums>
 
     <enums namespace="GL" start="0x8980" end="0x898F" vendor="OML">
@@ -5970,9 +6134,13 @@
         <enum value="0x898F" name="GL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS_OES"/>
     </enums>
 
-    <enums namespace="GL" start="0x8990" end="0x899F" vendor="ZiiLabs"/>
+    <enums namespace="GL" start="0x8990" end="0x899F" vendor="ZiiLabs">
+            <unused start="0x8990" end="0x899F" vendor="ZiiLabs"/>
+    </enums>
 
-    <enums namespace="GL" start="0x89A0" end="0x89FF" vendor="Matrox"/>
+    <enums namespace="GL" start="0x89A0" end="0x89FF" vendor="Matrox">
+            <unused start="0x89A0" end="0x89FF" vendor="Matrox"/>
+    </enums>
 
     <enums namespace="GL" start="0x8A00" end="0x8A7F" vendor="APPLE">
         <enum value="0x8A00" name="GL_VERTEX_ATTRIB_MAP1_APPLE"/>
@@ -5991,7 +6159,7 @@
         <enum value="0x8A0D" name="GL_ELEMENT_ARRAY_TYPE_APPLE"/>
         <enum value="0x8A0E" name="GL_ELEMENT_ARRAY_POINTER_APPLE"/>
         <enum value="0x8A0F" name="GL_COLOR_FLOAT_APPLE"/>
-            <unused start="0x8A10" comment="Unknown extension (Khronos bug 632)"/>
+            <unused start="0x8A10" vendor="APPLE" comment="Unknown extension (Khronos bug 632)"/>
             <!-- <enum value="0x8A10" name="GL_MIN_PBUFFER_VIEWPORT_DIMS_APPLE"/> -->
         <enum value="0x8A11" name="GL_UNIFORM_BUFFER"/>
         <enum value="0x8A12" name="GL_BUFFER_SERIALIZED_MODIFY_APPLE"/>
@@ -5999,21 +6167,22 @@
         <enum value="0x8A14" name="GL_AUX_DEPTH_STENCIL_APPLE"/>
         <enum value="0x8A15" name="GL_PACK_ROW_BYTES_APPLE"/>
         <enum value="0x8A16" name="GL_UNPACK_ROW_BYTES_APPLE"/>
-            <unused start="0x8A17" end="0x8A18"/>
+            <unused start="0x8A17" end="0x8A18" vendor="APPLE"/>
         <enum value="0x8A19" name="GL_RELEASED_APPLE"/>
         <enum value="0x8A1A" name="GL_VOLATILE_APPLE"/>
         <enum value="0x8A1B" name="GL_RETAINED_APPLE"/>
         <enum value="0x8A1C" name="GL_UNDEFINED_APPLE"/>
         <enum value="0x8A1D" name="GL_PURGEABLE_APPLE"/>
-            <unused start="0x8A1E"/>
+            <unused start="0x8A1E" vendor="APPLE"/>
         <enum value="0x8A1F" name="GL_RGB_422_APPLE"/>
-            <unused start="0x8A20" end="0x8A27"/>
+            <unused start="0x8A20" end="0x8A27" vendor="APPLE"/>
         <enum value="0x8A28" name="GL_UNIFORM_BUFFER_BINDING"/>
         <enum value="0x8A29" name="GL_UNIFORM_BUFFER_START"/>
         <enum value="0x8A2A" name="GL_UNIFORM_BUFFER_SIZE"/>
         <enum value="0x8A2B" name="GL_MAX_VERTEX_UNIFORM_BLOCKS"/>
         <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
-        <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT"/>                     
+        <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT"/>
+        <enum value="0x8A2C" name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES"/>
         <enum value="0x8A2D" name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS"/>
         <enum value="0x8A2E" name="GL_MAX_COMBINED_UNIFORM_BLOCKS"/>
         <enum value="0x8A2F" name="GL_MAX_UNIFORM_BUFFER_BINDINGS"/>
@@ -6021,6 +6190,7 @@
         <enum value="0x8A31" name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"/>
         <enum value="0x8A32" name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
         <enum value="0x8A32" name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8A32" name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
         <enum value="0x8A33" name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"/>
         <enum value="0x8A34" name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"/>
         <enum value="0x8A35" name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"/>
@@ -6041,13 +6211,13 @@
         <enum value="0x8A44" name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"/>
         <enum value="0x8A45" name="GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"/>
         <enum value="0x8A46" name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"/>
-            <unused start="0x8A47"/>
+            <unused start="0x8A47" vendor="APPLE"/>
         <enum value="0x8A48" name="GL_TEXTURE_SRGB_DECODE_EXT"/>
         <enum value="0x8A49" name="GL_DECODE_EXT"/>
         <enum value="0x8A4A" name="GL_SKIP_DECODE_EXT"/>
-            <unused start="0x8A4B" end="0x8A4E"/>
+            <unused start="0x8A4B" end="0x8A4E" vendor="APPLE"/>
         <enum value="0x8A4F" name="GL_PROGRAM_PIPELINE_OBJECT_EXT"/>
-            <unused start="0x8A50"/>
+            <unused start="0x8A50" vendor="APPLE"/>
         <enum value="0x8A51" name="GL_RGB_RAW_422_APPLE"/>
         <enum value="0x8A52" name="GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT"/>
         <enum value="0x8A53" name="GL_SYNC_OBJECT_APPLE"/>
@@ -6055,12 +6225,16 @@
         <enum value="0x8A55" name="GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT"/>
         <enum value="0x8A56" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT"/>
         <enum value="0x8A57" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT"/>
-            <unused start="0x8A58" end="0x8A7F"/>
+            <unused start="0x8A58" end="0x8A7F" vendor="APPLE"/>
     </enums>
 
-    <enums namespace="GL" start="0x8A80" end="0x8AEF" vendor="Matrox"/>
+    <enums namespace="GL" start="0x8A80" end="0x8AEF" vendor="Matrox">
+            <unused start="0x8A80" end="0x8AEF" vendor="Matrox"/>
+    </enums>
 
-    <enums namespace="GL" start="0x8AF0" end="0x8B2F" vendor="Chromium" comment="For Brian Paul"/>
+    <enums namespace="GL" start="0x8AF0" end="0x8B2F" vendor="Chromium" comment="For Brian Paul">
+            <unused start="0x8AF0" end="0x8B2F" vendor="Chromium"/>
+    </enums>
 
     <enums namespace="GL" start="0x8B30" end="0x8B3F" group="ShaderType" vendor="ARB">
         <enum value="0x8B30" name="GL_FRAGMENT_SHADER"/>
@@ -6186,7 +6360,7 @@
         <enum value="0x8B8C" name="GL_SHADING_LANGUAGE_VERSION_ARB"/>
         <enum value="0x8B8D" name="GL_CURRENT_PROGRAM"/>
         <enum value="0x8B8D" api="gl" name="GL_ACTIVE_PROGRAM_EXT" alias="GL_CURRENT_PROGRAM" comment="For the OpenGL version of EXT_separate_shader_objects"/>
-            <unused start="0x8B8E" end="0x8B8F"/>
+            <unused start="0x8B8E" end="0x8B8F" vendor="ARB"/>
     </enums>
 
     <enums namespace="GL" start="0x8B90" end="0x8B9F" vendor="OES">
@@ -6210,7 +6384,9 @@
         <enum value="0x8B9F" name="GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES"/>
     </enums>
 
-    <enums namespace="GL" start="0x8BA0" end="0x8BAF" vendor="Seaweed"/>
+    <enums namespace="GL" start="0x8BA0" end="0x8BAF" vendor="Seaweed">
+            <unused start="0x8BA0" end="0x8BAF" vendor="Seaweed"/>
+    </enums>
 
     <enums namespace="GL" start="0x8BB0" end="0x8BBF" vendor="MESA">
         <enum value="0x8BB0" name="GL_FRAGMENT_PROGRAM_POSITION_MESA"/>
@@ -6223,7 +6399,7 @@
         <enum value="0x8BB7" name="GL_VERTEX_PROGRAM_CALLBACK_DATA_MESA"/>
     </enums>
 
-    <enums namespace="GL" start="0x8BC0" end="0x8BFF" vendor="AMD">
+    <enums namespace="GL" start="0x8BC0" end="0x8BFF" vendor="QCOM" comment="Reassigned from AMD to QCOM">
         <enum value="0x8BC0" name="GL_COUNTER_TYPE_AMD"/>
         <enum value="0x8BC1" name="GL_COUNTER_RANGE_AMD"/>
         <enum value="0x8BC2" name="GL_UNSIGNED_INT64_AMD"/>
@@ -6231,7 +6407,7 @@
         <enum value="0x8BC4" name="GL_PERFMON_RESULT_AVAILABLE_AMD"/>
         <enum value="0x8BC5" name="GL_PERFMON_RESULT_SIZE_AMD"/>
         <enum value="0x8BC6" name="GL_PERFMON_RESULT_AMD"/>
-            <unused start="0x8BC7" end="0x8BD1"/>
+            <unused start="0x8BC7" end="0x8BD1" vendor="QCOM"/>
         <enum value="0x8BD2" name="GL_TEXTURE_WIDTH_QCOM"/>
         <enum value="0x8BD3" name="GL_TEXTURE_HEIGHT_QCOM"/>
         <enum value="0x8BD4" name="GL_TEXTURE_DEPTH_QCOM"/>
@@ -6243,7 +6419,9 @@
         <enum value="0x8BDA" name="GL_TEXTURE_TARGET_QCOM"/>
         <enum value="0x8BDB" name="GL_TEXTURE_OBJECT_VALID_QCOM"/>
         <enum value="0x8BDC" name="GL_STATE_RESTORE"/>
-            <unused start="0x8BDD" end="0x8BFF"/>
+            <unused start="0x8BDD" end="0x8BE6" vendor="QCOM"/>
+        <enum value="0x8BE7" name="GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT"/>
+            <unused start="0x8BE8" end="0x8BFF" vendor="QCOM"/>
     </enums>
 
     <enums namespace="GL" start="0x8C00" end="0x8C0F" vendor="IMG">
@@ -6258,7 +6436,7 @@
         <enum value="0x8C08" name="GL_FRAGMENT_ALPHA_MODULATE_IMG"/>
         <enum value="0x8C09" name="GL_ADD_BLEND_IMG"/>
         <enum value="0x8C0A" name="GL_SGX_BINARY_IMG"/>
-            <unused start="0x8C0B" end="0x8C0F"/>
+            <unused start="0x8C0B" end="0x8C0F" vendor="IMG"/>
     </enums>
 
     <enums namespace="GL" start="0x8C10" end="0x8C8F" vendor="NV" comment="For Pat Brown">
@@ -6291,47 +6469,57 @@
         <enum value="0x8C1C" name="GL_TEXTURE_BINDING_1D_ARRAY_EXT"/>
         <enum value="0x8C1D" name="GL_TEXTURE_BINDING_2D_ARRAY"/>
         <enum value="0x8C1D" name="GL_TEXTURE_BINDING_2D_ARRAY_EXT"/>
-            <unused start="0x8C1E" end="0x8C25"/>
+            <unused start="0x8C1E" end="0x8C25" vendor="NV"/>
         <enum value="0x8C26" name="GL_GEOMETRY_PROGRAM_NV"/>
         <enum value="0x8C27" name="GL_MAX_PROGRAM_OUTPUT_VERTICES_NV"/>
         <enum value="0x8C28" name="GL_MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV"/>
         <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"/>
         <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB"/>
         <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT"/>
+        <enum value="0x8C29" name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES"/>
         <enum value="0x8C2A" name="GL_TEXTURE_BUFFER"/>
         <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_ARB"/>
         <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_EXT"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_OES"/>
         <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING" comment="Equivalent to GL_TEXTURE_BUFFER_ARB query, but named more consistently"/>
-        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING_EXT"/>                          
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING_EXT"/>
+        <enum value="0x8C2A" name="GL_TEXTURE_BUFFER_BINDING_OES"/>
         <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE"/>
         <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE_ARB"/>
         <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE_EXT"/>
+        <enum value="0x8C2B" name="GL_MAX_TEXTURE_BUFFER_SIZE_OES"/>
         <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER"/>
         <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER_ARB"/>
         <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER_EXT"/>
+        <enum value="0x8C2C" name="GL_TEXTURE_BINDING_BUFFER_OES"/>
         <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING"/>
         <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_ARB"/>
         <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT"/>
+        <enum value="0x8C2D" name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES"/>
         <enum value="0x8C2E" name="GL_TEXTURE_BUFFER_FORMAT_ARB"/>
         <enum value="0x8C2E" name="GL_TEXTURE_BUFFER_FORMAT_EXT"/>
         <enum value="0x8C2F" name="GL_ANY_SAMPLES_PASSED"/>
         <enum value="0x8C2F" name="GL_ANY_SAMPLES_PASSED_EXT"/>
-            <unused start="0x8C30" end="0x8C35"/>
+            <unused start="0x8C30" end="0x8C35" vendor="NV"/>
         <enum value="0x8C36" name="GL_SAMPLE_SHADING"/>
         <enum value="0x8C36" name="GL_SAMPLE_SHADING_ARB"/>
         <enum value="0x8C36" name="GL_SAMPLE_SHADING_OES"/>
         <enum value="0x8C37" name="GL_MIN_SAMPLE_SHADING_VALUE"/>
         <enum value="0x8C37" name="GL_MIN_SAMPLE_SHADING_VALUE_ARB"/>
         <enum value="0x8C37" name="GL_MIN_SAMPLE_SHADING_VALUE_OES"/>
-            <unused start="0x8C38" end="0x8C39"/>
+            <unused start="0x8C38" end="0x8C39" vendor="NV"/>
         <enum value="0x8C3A" name="GL_R11F_G11F_B10F"/>
+        <enum value="0x8C3A" name="GL_R11F_G11F_B10F_APPLE"/>
         <enum value="0x8C3A" name="GL_R11F_G11F_B10F_EXT"/>
         <enum value="0x8C3B" name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
+        <enum value="0x8C3B" name="GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE"/>
         <enum value="0x8C3B" name="GL_UNSIGNED_INT_10F_11F_11F_REV_EXT"/>
         <enum value="0x8C3C" name="GL_RGBA_SIGNED_COMPONENTS_EXT"/>
         <enum value="0x8C3D" name="GL_RGB9_E5"/>
+        <enum value="0x8C3D" name="GL_RGB9_E5_APPLE"/>
         <enum value="0x8C3D" name="GL_RGB9_E5_EXT"/>
         <enum value="0x8C3E" name="GL_UNSIGNED_INT_5_9_9_9_REV"/>
+        <enum value="0x8C3E" name="GL_UNSIGNED_INT_5_9_9_9_REV_APPLE"/>
         <enum value="0x8C3E" name="GL_UNSIGNED_INT_5_9_9_9_REV_EXT"/>
         <enum value="0x8C3F" name="GL_TEXTURE_SHARED_SIZE"/>
         <enum value="0x8C3F" name="GL_TEXTURE_SHARED_SIZE_EXT"/>
@@ -6372,7 +6560,7 @@
         <enum value="0x8C4E" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV"/>
         <enum value="0x8C4F" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"/>
         <enum value="0x8C4F" name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV"/>
-            <unused start="0x8C50" end="0x8C6F"/>
+            <unused start="0x8C50" end="0x8C6F" vendor="NV"/>
         <enum value="0x8C70" name="GL_COMPRESSED_LUMINANCE_LATC1_EXT"/>
         <enum value="0x8C71" name="GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT"/>
         <enum value="0x8C72" name="GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT"/>
@@ -6410,6 +6598,7 @@
         <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED"/>
         <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED_EXT"/>
         <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED_NV"/>
+        <enum value="0x8C87" name="GL_PRIMITIVES_GENERATED_OES"/>
         <enum value="0x8C88" name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"/>
         <enum value="0x8C88" name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT"/>
         <enum value="0x8C88" name="GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV"/>
@@ -6436,13 +6625,11 @@
         <enum value="0x8C8F" name="GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_NV"/>
     </enums>
 
-    <enums namespace="GL" start="0x8C90" end="0x8C9F" vendor="QCOM" comment="For Affie Munshi, OpenGL ES extensions">
-            <!-- Reassigned from ATI to QCOM at time of
-                 mobile/desktop split (bug 5874) -->
-            <unused start="0x8C90" end="0x8C91"/>
+    <enums namespace="GL" start="0x8C90" end="0x8C9F" vendor="QCOM" comment="For Affie Munshi. Reassigned from AMD to QCOM (bug 5874)">
+            <unused start="0x8C90" end="0x8C91" vendor="QCOM"/>
         <enum value="0x8C92" name="GL_ATC_RGB_AMD"/>
         <enum value="0x8C93" name="GL_ATC_RGBA_EXPLICIT_ALPHA_AMD"/>
-            <unused start="0x8C94" end="0x8C9F"/>
+            <unused start="0x8C94" end="0x8C9F" vendor="QCOM"/>
     </enums>
 
     <enums namespace="GL" start="0x8CA0" end="0x8CAF" vendor="ARB">
@@ -6488,10 +6675,12 @@
         <enum value="0x8CAB" name="GL_RENDERBUFFER_SAMPLES_NV"/>
         <enum value="0x8CAC" name="GL_DEPTH_COMPONENT32F"/>
         <enum value="0x8CAD" name="GL_DEPTH32F_STENCIL8"/>
-            <unused start="0x8CAE" end="0x8CAF"/>
+            <unused start="0x8CAE" end="0x8CAF" vendor="ARB"/>
     </enums>
 
-    <enums namespace="GL" start="0x8CB0" end="0x8CCF" vendor="ZiiLabs" comment="For Barthold Lichtenbelt 2004/12/1"/>
+    <enums namespace="GL" start="0x8CB0" end="0x8CCF" vendor="ZiiLabs" comment="For Barthold Lichtenbelt 2004/12/1">
+            <unused start="0x8CB0" end="0x8CCF" vendor="ZiiLabs"/>
+    </enums>
 
     <enums namespace="GL" start="0x8CD0" end="0x8D5F" vendor="ARB" comment="Framebuffer object specification + headroom">
         <enum value="0x8CD0" name="GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE"/>
@@ -6519,7 +6708,7 @@
         <enum value="0x8CD7" name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"/>
         <enum value="0x8CD7" name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT"/>
         <enum value="0x8CD7" name="GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES"/>
-            <unused start="0x8CD8" comment="Removed 2005/09/26 in revision #117 of the FBO extension spec"/>
+            <unused start="0x8CD8" vendor="ARB" comment="Removed 2005/09/26 in revision #117 of the FBO extension spec"/>
             <!-- <enum value="0x8CD8" name="GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT"/> -->
         <enum value="0x8CD9" name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"/>
         <enum value="0x8CD9" name="GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT"/>
@@ -6535,7 +6724,7 @@
         <enum value="0x8CDD" name="GL_FRAMEBUFFER_UNSUPPORTED"/>
         <enum value="0x8CDD" name="GL_FRAMEBUFFER_UNSUPPORTED_EXT"/>
         <enum value="0x8CDD" name="GL_FRAMEBUFFER_UNSUPPORTED_OES"/>
-            <unused start="0x8CDE" comment="Removed 2005/05/31 in revision #113 of the FBO extension spec"/>
+            <unused start="0x8CDE" vendor="ARB" comment="Removed 2005/05/31 in revision #113 of the FBO extension spec"/>
             <!-- <enum value="0x8CDE" name="GL_FRAMEBUFFER_STATUS_ERROR_EXT"/> -->
         <enum value="0x8CDF" name="GL_MAX_COLOR_ATTACHMENTS"/>
         <enum value="0x8CDF" name="GL_MAX_COLOR_ATTACHMENTS_EXT"/>
@@ -6589,15 +6778,30 @@
         <enum value="0x8CEF" name="GL_COLOR_ATTACHMENT15"/>
         <enum value="0x8CEF" name="GL_COLOR_ATTACHMENT15_EXT"/>
         <enum value="0x8CEF" name="GL_COLOR_ATTACHMENT15_NV"/>
-            <unused start="0x8CF0" end="0x8CFF" comment="For color attachments 16-31"/>
+        <enum value="0x8CF0" name="GL_COLOR_ATTACHMENT16"/>
+        <enum value="0x8CF1" name="GL_COLOR_ATTACHMENT17"/>
+        <enum value="0x8CF2" name="GL_COLOR_ATTACHMENT18"/>
+        <enum value="0x8CF3" name="GL_COLOR_ATTACHMENT19"/>
+        <enum value="0x8CF4" name="GL_COLOR_ATTACHMENT20"/>
+        <enum value="0x8CF5" name="GL_COLOR_ATTACHMENT21"/>
+        <enum value="0x8CF6" name="GL_COLOR_ATTACHMENT22"/>
+        <enum value="0x8CF7" name="GL_COLOR_ATTACHMENT23"/>
+        <enum value="0x8CF8" name="GL_COLOR_ATTACHMENT24"/>
+        <enum value="0x8CF9" name="GL_COLOR_ATTACHMENT25"/>
+        <enum value="0x8CFA" name="GL_COLOR_ATTACHMENT26"/>
+        <enum value="0x8CFB" name="GL_COLOR_ATTACHMENT27"/>
+        <enum value="0x8CFC" name="GL_COLOR_ATTACHMENT28"/>
+        <enum value="0x8CFD" name="GL_COLOR_ATTACHMENT29"/>
+        <enum value="0x8CFE" name="GL_COLOR_ATTACHMENT30"/>
+        <enum value="0x8CFF" name="GL_COLOR_ATTACHMENT31"/>
         <enum value="0x8D00" name="GL_DEPTH_ATTACHMENT"/>
         <enum value="0x8D00" name="GL_DEPTH_ATTACHMENT_EXT"/>
         <enum value="0x8D00" name="GL_DEPTH_ATTACHMENT_OES"/>
-            <unused start="0x8D01" end="0x8D1F" comment="For depth attachments 16-31"/>
+            <unused start="0x8D01" end="0x8D1F" vendor="ARB" comment="For depth attachments 16-31"/>
         <enum value="0x8D20" name="GL_STENCIL_ATTACHMENT"/>
         <enum value="0x8D20" name="GL_STENCIL_ATTACHMENT_EXT"/>
         <enum value="0x8D20" name="GL_STENCIL_ATTACHMENT_OES"/>
-            <unused start="0x8D21" end="0x8D3F" comment="For stencil attachments 16-31"/>
+            <unused start="0x8D21" end="0x8D3F" vendor="ARB" comment="For stencil attachments 16-31"/>
         <enum value="0x8D40" name="GL_FRAMEBUFFER"/>
         <enum value="0x8D40" name="GL_FRAMEBUFFER_EXT"/>
         <enum value="0x8D40" name="GL_FRAMEBUFFER_OES"/>
@@ -6613,7 +6817,7 @@
         <enum value="0x8D44" name="GL_RENDERBUFFER_INTERNAL_FORMAT"/>
         <enum value="0x8D44" name="GL_RENDERBUFFER_INTERNAL_FORMAT_EXT"/>
         <enum value="0x8D44" name="GL_RENDERBUFFER_INTERNAL_FORMAT_OES"/>
-            <unused start="0x8D45" comment="Was for GL_STENCIL_INDEX_EXT, but now use core STENCIL_INDEX instead"/>
+            <unused start="0x8D45" vendor="ARB" comment="Was for GL_STENCIL_INDEX_EXT, but now use core STENCIL_INDEX instead"/>
         <enum value="0x8D46" name="GL_STENCIL_INDEX1"/>
         <enum value="0x8D46" name="GL_STENCIL_INDEX1_EXT"/>
         <enum value="0x8D46" name="GL_STENCIL_INDEX1_OES"/>
@@ -6625,7 +6829,7 @@
         <enum value="0x8D48" name="GL_STENCIL_INDEX8_OES"/>
         <enum value="0x8D49" name="GL_STENCIL_INDEX16"/>
         <enum value="0x8D49" name="GL_STENCIL_INDEX16_EXT"/>
-            <unused start="0x8D4A" end="0x8D4F" comment="For additional stencil formats"/>
+            <unused start="0x8D4A" end="0x8D4F" vendor="ARB" comment="For additional stencil formats"/>
         <enum value="0x8D50" name="GL_RENDERBUFFER_RED_SIZE"/>
         <enum value="0x8D50" name="GL_RENDERBUFFER_RED_SIZE_EXT"/>
         <enum value="0x8D50" name="GL_RENDERBUFFER_RED_SIZE_OES"/>
@@ -6654,7 +6858,7 @@
         <enum value="0x8D57" name="GL_MAX_SAMPLES_APPLE"/>
         <enum value="0x8D57" name="GL_MAX_SAMPLES_EXT"/>
         <enum value="0x8D57" name="GL_MAX_SAMPLES_NV"/>
-            <unused start="0x8D58" end="0x8D5F"/>
+            <unused start="0x8D58" end="0x8D5F" vendor="ARB"/>
     </enums>
 
     <enums namespace="GL" start="0x8D60" end="0x8D6F" vendor="OES">
@@ -6662,7 +6866,7 @@
         <enum value="0x8D61" name="GL_HALF_FLOAT_OES"/>
         <enum value="0x8D62" name="GL_RGB565_OES"/>
         <enum value="0x8D62" name="GL_RGB565"/>
-            <unused start="0x8D63" comment="Was GL_TEXTURE_IMMUTABLE_LEVELS in draft ES 3.0 spec"/>
+            <unused start="0x8D63" vendor="OES" comment="Was GL_TEXTURE_IMMUTABLE_LEVELS in draft ES 3.0 spec"/>
         <enum value="0x8D64" name="GL_ETC1_RGB8_OES"/>
         <enum value="0x8D65" name="GL_TEXTURE_EXTERNAL_OES"/>
         <enum value="0x8D66" name="GL_SAMPLER_EXTERNAL_OES"/>
@@ -6673,7 +6877,7 @@
         <enum value="0x8D6A" name="GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT"/>
         <enum value="0x8D6B" name="GL_MAX_ELEMENT_INDEX"/>
         <enum value="0x8D6C" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT"/>
-            <unused start="0x8D6D" end="0x8D6F"/>
+            <unused start="0x8D6D" end="0x8D6F" vendor="OES"/>
     </enums>
 
     <enums namespace="GL" start="0x8D70" end="0x8DEF" vendor="NV" comment="For Pat Brown 2005/10/13">
@@ -6755,9 +6959,11 @@
         <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED"/>
         <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_ARB"/>
         <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT"/>
+        <enum value="0x8DA7" name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES"/>
         <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"/>
         <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB"/>
         <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT"/>
+        <enum value="0x8DA8" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES"/>
         <enum value="0x8DA9" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB"/>
         <enum value="0x8DA9" name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT"/>
             <!-- Also see the odd namespace "NVTransformFeedbackToken" above -->
@@ -6768,7 +6974,7 @@
         <enum value="0x8DAD" name="GL_FLOAT_32_UNSIGNED_INT_24_8_REV_NV"/>
         <enum value="0x8DAE" name="GL_SHADER_INCLUDE_ARB"/>
         <enum value="0x8DAF" name="GL_DEPTH_BUFFER_FLOAT_MODE_NV"/>
-            <unused start="0x8DB0" end="0x8DB8"/>
+            <unused start="0x8DB0" end="0x8DB8" vendor="NV"/>
         <enum value="0x8DB9" name="GL_FRAMEBUFFER_SRGB"/>
         <enum value="0x8DB9" name="GL_FRAMEBUFFER_SRGB_EXT"/>
         <enum value="0x8DBA" name="GL_FRAMEBUFFER_SRGB_CAPABLE_EXT"/>
@@ -6786,6 +6992,7 @@
         <enum value="0x8DC1" name="GL_SAMPLER_2D_ARRAY_EXT"/>
         <enum value="0x8DC2" name="GL_SAMPLER_BUFFER"/>
         <enum value="0x8DC2" name="GL_SAMPLER_BUFFER_EXT"/>
+        <enum value="0x8DC2" name="GL_SAMPLER_BUFFER_OES"/>
         <enum value="0x8DC3" name="GL_SAMPLER_1D_ARRAY_SHADOW"/>
         <enum value="0x8DC3" name="GL_SAMPLER_1D_ARRAY_SHADOW_EXT"/>
         <enum value="0x8DC4" name="GL_SAMPLER_2D_ARRAY_SHADOW"/>
@@ -6816,6 +7023,7 @@
         <enum value="0x8DCF" name="GL_INT_SAMPLER_2D_ARRAY_EXT"/>
         <enum value="0x8DD0" name="GL_INT_SAMPLER_BUFFER"/>
         <enum value="0x8DD0" name="GL_INT_SAMPLER_BUFFER_EXT"/>
+        <enum value="0x8DD0" name="GL_INT_SAMPLER_BUFFER_OES"/>
         <enum value="0x8DD1" name="GL_UNSIGNED_INT_SAMPLER_1D"/>
         <enum value="0x8DD1" name="GL_UNSIGNED_INT_SAMPLER_1D_EXT"/>
         <enum value="0x8DD2" name="GL_UNSIGNED_INT_SAMPLER_2D"/>
@@ -6832,9 +7040,11 @@
         <enum value="0x8DD7" name="GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT"/>
         <enum value="0x8DD8" name="GL_UNSIGNED_INT_SAMPLER_BUFFER"/>
         <enum value="0x8DD8" name="GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT"/>
+        <enum value="0x8DD8" name="GL_UNSIGNED_INT_SAMPLER_BUFFER_OES"/>
         <enum value="0x8DD9" name="GL_GEOMETRY_SHADER"/>
         <enum value="0x8DD9" name="GL_GEOMETRY_SHADER_ARB"/>
         <enum value="0x8DD9" name="GL_GEOMETRY_SHADER_EXT"/>
+        <enum value="0x8DD9" name="GL_GEOMETRY_SHADER_OES"/>
         <enum value="0x8DDA" name="GL_GEOMETRY_VERTICES_OUT_ARB"/>
         <enum value="0x8DDA" name="GL_GEOMETRY_VERTICES_OUT_EXT"/>
         <enum value="0x8DDB" name="GL_GEOMETRY_INPUT_TYPE_ARB"/>
@@ -6848,12 +7058,15 @@
         <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"/>
         <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB"/>
         <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8DDF" name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
         <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES"/>
         <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_ARB"/>
         <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT"/>
+        <enum value="0x8DE0" name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES"/>
         <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"/>
         <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB"/>
         <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8DE1" name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES"/>
         <enum value="0x8DE2" name="GL_MAX_VERTEX_BINDABLE_UNIFORMS_EXT"/>
         <enum value="0x8DE3" name="GL_MAX_FRAGMENT_BINDABLE_UNIFORMS_EXT"/>
         <enum value="0x8DE4" name="GL_MAX_GEOMETRY_BINDABLE_UNIFORMS_EXT"/>
@@ -6863,7 +7076,7 @@
         <enum value="0x8DE8" name="GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS"/>
         <enum value="0x8DE9" name="GL_NAMED_STRING_LENGTH_ARB"/>
         <enum value="0x8DEA" name="GL_NAMED_STRING_TYPE_ARB"/>
-            <unused start="0x8DEB" end="0x8DEC"/>
+            <unused start="0x8DEB" end="0x8DEC" vendor="NV"/>
         <enum value="0x8DED" name="GL_MAX_BINDABLE_UNIFORM_SIZE_EXT"/>
         <enum value="0x8DEE" name="GL_UNIFORM_BUFFER_EXT"/>
         <enum value="0x8DEF" name="GL_UNIFORM_BUFFER_BINDING_EXT"/>
@@ -6884,7 +7097,7 @@
         <enum value="0x8DFB" name="GL_MAX_VERTEX_UNIFORM_VECTORS"/>
         <enum value="0x8DFC" name="GL_MAX_VARYING_VECTORS"/>
         <enum value="0x8DFD" name="GL_MAX_FRAGMENT_UNIFORM_VECTORS"/>
-            <unused start="0x8DFE" end="0x8E0F"/>
+            <unused start="0x8DFE" end="0x8E0F" vendor="OES"/>
     </enums>
 
     <enums namespace="GL" start="0x8E10" end="0x8E8F" vendor="NV" comment="For Michael Gold 2006/08/07">
@@ -6899,13 +7112,20 @@
         <enum value="0x8E15" name="GL_QUERY_BY_REGION_WAIT_NV"/>
         <enum value="0x8E16" name="GL_QUERY_BY_REGION_NO_WAIT"/>
         <enum value="0x8E16" name="GL_QUERY_BY_REGION_NO_WAIT_NV"/>
-            <unused start="0x8E17" end="0x8E1D"/>
+        <enum value="0x8E17" name="GL_QUERY_WAIT_INVERTED"/>
+        <enum value="0x8E18" name="GL_QUERY_NO_WAIT_INVERTED"/>
+        <enum value="0x8E19" name="GL_QUERY_BY_REGION_WAIT_INVERTED"/>
+        <enum value="0x8E1A" name="GL_QUERY_BY_REGION_NO_WAIT_INVERTED"/>
+        <enum value="0x8E1B" name="GL_POLYGON_OFFSET_CLAMP_EXT"/>
+            <unused start="0x8E1C" end="0x8E1D" vendor="NV"/>
         <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"/>
-        <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>    
+        <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E1E" name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
         <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
-        <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/> 
+        <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E1F" name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
         <enum value="0x8E20" name="GL_COLOR_SAMPLES_NV"/>
-            <unused start="0x8E21"/>
+            <unused start="0x8E21" vendor="NV"/>
         <enum value="0x8E22" name="GL_TRANSFORM_FEEDBACK"/>
         <enum value="0x8E22" name="GL_TRANSFORM_FEEDBACK_NV"/>
         <enum value="0x8E23" name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED"/>
@@ -6928,7 +7148,7 @@
         <enum value="0x8E2D" name="GL_PROGRAM_MATRIX_EXT"/>
         <enum value="0x8E2E" name="GL_TRANSPOSE_PROGRAM_MATRIX_EXT"/>
         <enum value="0x8E2F" name="GL_PROGRAM_MATRIX_STACK_DEPTH_EXT"/>
-            <unused start="0x8E30" end="0x8E41"/>
+            <unused start="0x8E30" end="0x8E41" vendor="NV"/>
         <enum value="0x8E42" name="GL_TEXTURE_SWIZZLE_R"/>
         <enum value="0x8E42" name="GL_TEXTURE_SWIZZLE_R_EXT"/>
         <enum value="0x8E43" name="GL_TEXTURE_SWIZZLE_G"/>
@@ -6948,12 +7168,16 @@
         <enum value="0x8E4C" name="GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT"/>
         <enum value="0x8E4D" name="GL_FIRST_VERTEX_CONVENTION"/>
         <enum value="0x8E4D" name="GL_FIRST_VERTEX_CONVENTION_EXT"/>
+        <enum value="0x8E4D" name="GL_FIRST_VERTEX_CONVENTION_OES"/>
         <enum value="0x8E4E" name="GL_LAST_VERTEX_CONVENTION"/>
         <enum value="0x8E4E" name="GL_LAST_VERTEX_CONVENTION_EXT"/>
+        <enum value="0x8E4E" name="GL_LAST_VERTEX_CONVENTION_OES"/>
         <enum value="0x8E4F" name="GL_PROVOKING_VERTEX"/>
         <enum value="0x8E4F" name="GL_PROVOKING_VERTEX_EXT"/>
         <enum value="0x8E50" name="GL_SAMPLE_POSITION"/>
         <enum value="0x8E50" name="GL_SAMPLE_POSITION_NV"/>
+        <enum value="0x8E50" name="GL_SAMPLE_LOCATION_ARB" alias="GL_SAMPLE_POSITION"/>
+        <enum value="0x8E50" name="GL_SAMPLE_LOCATION_NV" alias="GL_SAMPLE_POSITION_NV"/>
         <enum value="0x8E51" name="GL_SAMPLE_MASK"/>
         <enum value="0x8E51" name="GL_SAMPLE_MASK_NV"/>
         <enum value="0x8E52" name="GL_SAMPLE_MASK_VALUE"/>
@@ -6968,7 +7192,8 @@
         <enum value="0x8E59" name="GL_MAX_SAMPLE_MASK_WORDS_NV"/>
         <enum value="0x8E5A" name="GL_MAX_GEOMETRY_PROGRAM_INVOCATIONS_NV"/>
         <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS"/>
-        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT"/>                 
+        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT"/>
+        <enum value="0x8E5A" name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES"/>
         <enum value="0x8E5B" name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"/>
         <enum value="0x8E5B" name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
         <enum value="0x8E5B" name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_NV"/>
@@ -6984,60 +7209,83 @@
         <enum value="0x8E5F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET"/>
         <enum value="0x8E5F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_ARB"/>
         <enum value="0x8E5F" name="GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET_NV"/>
-            <unused start="0x8E60" end="0x8E6F"/>
+            <unused start="0x8E60" end="0x8E6F" vendor="NV"/>
         <enum value="0x8E70" name="GL_MAX_TRANSFORM_FEEDBACK_BUFFERS"/>
         <enum value="0x8E71" name="GL_MAX_VERTEX_STREAMS"/>
         <enum value="0x8E72" name="GL_PATCH_VERTICES"/>
         <enum value="0x8E72" name="GL_PATCH_VERTICES_EXT"/>
+        <enum value="0x8E72" name="GL_PATCH_VERTICES_OES"/>
         <enum value="0x8E73" name="GL_PATCH_DEFAULT_INNER_LEVEL"/>
         <enum value="0x8E73" name="GL_PATCH_DEFAULT_INNER_LEVEL_EXT"/>
         <enum value="0x8E74" name="GL_PATCH_DEFAULT_OUTER_LEVEL"/>
         <enum value="0x8E74" name="GL_PATCH_DEFAULT_OUTER_LEVEL_EXT"/>
         <enum value="0x8E75" name="GL_TESS_CONTROL_OUTPUT_VERTICES"/>
         <enum value="0x8E75" name="GL_TESS_CONTROL_OUTPUT_VERTICES_EXT"/>
+        <enum value="0x8E75" name="GL_TESS_CONTROL_OUTPUT_VERTICES_OES"/>
         <enum value="0x8E76" name="GL_TESS_GEN_MODE"/>
         <enum value="0x8E76" name="GL_TESS_GEN_MODE_EXT"/>
+        <enum value="0x8E76" name="GL_TESS_GEN_MODE_OES"/>
         <enum value="0x8E77" name="GL_TESS_GEN_SPACING"/>
         <enum value="0x8E77" name="GL_TESS_GEN_SPACING_EXT"/>
+        <enum value="0x8E77" name="GL_TESS_GEN_SPACING_OES"/>
         <enum value="0x8E78" name="GL_TESS_GEN_VERTEX_ORDER"/>
         <enum value="0x8E78" name="GL_TESS_GEN_VERTEX_ORDER_EXT"/>
+        <enum value="0x8E78" name="GL_TESS_GEN_VERTEX_ORDER_OES"/>
         <enum value="0x8E79" name="GL_TESS_GEN_POINT_MODE"/>
         <enum value="0x8E79" name="GL_TESS_GEN_POINT_MODE_EXT"/>
+        <enum value="0x8E79" name="GL_TESS_GEN_POINT_MODE_OES"/>
         <enum value="0x8E7A" name="GL_ISOLINES"/>
         <enum value="0x8E7A" name="GL_ISOLINES_EXT"/>
+        <enum value="0x8E7A" name="GL_ISOLINES_OES"/>
         <enum value="0x8E7B" name="GL_FRACTIONAL_ODD"/>
         <enum value="0x8E7B" name="GL_FRACTIONAL_ODD_EXT"/>
+        <enum value="0x8E7B" name="GL_FRACTIONAL_ODD_OES"/>
         <enum value="0x8E7C" name="GL_FRACTIONAL_EVEN"/>
         <enum value="0x8E7C" name="GL_FRACTIONAL_EVEN_EXT"/>
+        <enum value="0x8E7C" name="GL_FRACTIONAL_EVEN_OES"/>
         <enum value="0x8E7D" name="GL_MAX_PATCH_VERTICES"/>
         <enum value="0x8E7D" name="GL_MAX_PATCH_VERTICES_EXT"/>
+        <enum value="0x8E7D" name="GL_MAX_PATCH_VERTICES_OES"/>
         <enum value="0x8E7E" name="GL_MAX_TESS_GEN_LEVEL"/>
         <enum value="0x8E7E" name="GL_MAX_TESS_GEN_LEVEL_EXT"/>
+        <enum value="0x8E7E" name="GL_MAX_TESS_GEN_LEVEL_OES"/>
         <enum value="0x8E7F" name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"/>
         <enum value="0x8E7F" name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E7F" name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
         <enum value="0x8E80" name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
         <enum value="0x8E80" name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT"/>
+        <enum value="0x8E80" name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
         <enum value="0x8E81" name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"/>
         <enum value="0x8E81" name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT"/>
+        <enum value="0x8E81" name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES"/>
         <enum value="0x8E82" name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"/>
         <enum value="0x8E82" name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT"/>
+        <enum value="0x8E82" name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES"/>
         <enum value="0x8E83" name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"/>
         <enum value="0x8E83" name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8E83" name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES"/>
         <enum value="0x8E84" name="GL_MAX_TESS_PATCH_COMPONENTS"/>
         <enum value="0x8E84" name="GL_MAX_TESS_PATCH_COMPONENTS_EXT"/>
+        <enum value="0x8E84" name="GL_MAX_TESS_PATCH_COMPONENTS_OES"/>
         <enum value="0x8E85" name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"/>
         <enum value="0x8E85" name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8E85" name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES"/>
         <enum value="0x8E86" name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"/>
         <enum value="0x8E86" name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x8E86" name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES"/>
         <enum value="0x8E87" name="GL_TESS_EVALUATION_SHADER"/>
         <enum value="0x8E87" name="GL_TESS_EVALUATION_SHADER_EXT"/>
+        <enum value="0x8E87" name="GL_TESS_EVALUATION_SHADER_OES"/>
         <enum value="0x8E88" name="GL_TESS_CONTROL_SHADER"/>
         <enum value="0x8E88" name="GL_TESS_CONTROL_SHADER_EXT"/>
+        <enum value="0x8E88" name="GL_TESS_CONTROL_SHADER_OES"/>
         <enum value="0x8E89" name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"/>
         <enum value="0x8E89" name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT"/>
+        <enum value="0x8E89" name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES"/>
         <enum value="0x8E8A" name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
         <enum value="0x8E8A" name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT"/>
-            <unused start="0x8E8B"/>
+        <enum value="0x8E8A" name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES"/>
+            <unused start="0x8E8B" vendor="NV"/>
         <enum value="0x8E8C" name="GL_COMPRESSED_RGBA_BPTC_UNORM"/>
         <enum value="0x8E8C" name="GL_COMPRESSED_RGBA_BPTC_UNORM_ARB"/>
         <enum value="0x8E8D" name="GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM"/>
@@ -7049,14 +7297,20 @@
     </enums>
 
     <enums namespace="GL" start="0x8E90" end="0x8E9F" vendor="QNX" comment="For QNX_texture_tiling, QNX_complex_polygon, QNX_stippled_lines (Khronos bug 696)">
-            <unused start="0x8E90" end="0x8E9F"/>
+            <unused start="0x8E90" end="0x8E9F" vendor="QNX"/>
     </enums>
 
-    <enums namespace="GL" start="0x8EA0" end="0x8EAF" vendor="IMG"/>
+    <enums namespace="GL" start="0x8EA0" end="0x8EAF" vendor="IMG">
+            <unused start="0x8EA0" end="0x8EAF" vendor="IMG"/>
+    </enums>
 
-    <enums namespace="GL" start="0x8EB0" end="0x8EBF" vendor="OES" comment="For Affie Munshi 2007/07/20"/>
+    <enums namespace="GL" start="0x8EB0" end="0x8EBF" vendor="OES" comment="For Affie Munshi 2007/07/20">
+            <unused start="0x8EB0" end="0x8EBF" vendor="OES"/>
+    </enums>
 
-    <enums namespace="GL" start="0x8EC0" end="0x8ECF" vendor="Vincent"/>
+    <enums namespace="GL" start="0x8EC0" end="0x8ECF" vendor="Vincent">
+            <unused start="0x8EC0" end="0x8ECF" vendor="Vincent"/>
+    </enums>
 
     <enums namespace="GL" start="0x8ED0" end="0x8F4F" vendor="NV" comment="For Pat Brown, Khronos bug 3191">
         <enum value="0x8ED0" name="GL_COVERAGE_COMPONENT_NV"/>
@@ -7067,7 +7321,7 @@
         <enum value="0x8ED5" name="GL_COVERAGE_ALL_FRAGMENTS_NV"/>
         <enum value="0x8ED6" name="GL_COVERAGE_EDGE_FRAGMENTS_NV"/>
         <enum value="0x8ED7" name="GL_COVERAGE_AUTOMATIC_NV"/>
-            <unused start="0x8ED8" end="0x8F1C"/>
+            <unused start="0x8ED8" end="0x8F1C" vendor="NV"/>
         <enum value="0x8F1D" name="GL_BUFFER_GPU_ADDRESS_NV"/>
         <enum value="0x8F1E" name="GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV"/>
         <enum value="0x8F1F" name="GL_ELEMENT_ARRAY_UNIFIED_NV"/>
@@ -7142,23 +7396,29 @@
         <enum value="0x8F4F" name="GL_VERTEX_BINDING_BUFFER"/>
     </enums>
 
-    <enums namespace="GL" start="0x8F50" end="0x8F5F" vendor="ZiiLabs" comment="For Jon Kennedy, Khronos public bug 75"/>
+    <enums namespace="GL" start="0x8F50" end="0x8F5F" vendor="ZiiLabs" comment="For Jon Kennedy, Khronos public bug 75">
+            <unused start="0x8F50" end="0x8F5F" vendor="ZiiLabs"/>
+    </enums>
 
     <enums namespace="GL" start="0x8F60" end="0x8F6F" vendor="ARM" comment="For Remi Pedersen, Khronos bug 3745">
         <enum value="0x8F60" name="GL_MALI_SHADER_BINARY_ARM"/>
         <enum value="0x8F61" name="GL_MALI_PROGRAM_BINARY_ARM"/>
-            <unused start="0x8F62"/>
+            <unused start="0x8F62" vendor="ARM"/>
         <enum value="0x8F63" name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT"/>
         <enum value="0x8F64" name="GL_SHADER_PIXEL_LOCAL_STORAGE_EXT"/>
         <enum value="0x8F65" name="GL_FETCH_PER_SAMPLE_ARM"/>
         <enum value="0x8F66" name="GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM"/>
         <enum value="0x8F67" name="GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT"/>
-            <unused start="0x8F68" end="0x8F6F"/>
+            <unused start="0x8F68" end="0x8F6F" vendor="ARM"/>
     </enums>
 
-    <enums namespace="GL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with EGL."/>
+    <enums namespace="GL" start="0x8F70" end="0x8F7F" vendor="HI" comment="For Mark Callow, Khronos bug 4055. Shared with EGL.">
+            <unused start="0x8F70" end="0x8F7F" vendor="HI"/>
+    </enums>
 
-    <enums namespace="GL" start="0x8F80" end="0x8F8F" vendor="Zebra" comment="For Mike Weiblen, public bug 910"/>
+    <enums namespace="GL" start="0x8F80" end="0x8F8F" vendor="Zebra" comment="For Mike Weiblen, public bug 910">
+            <unused start="0x8F80" end="0x8F8F" vendor="Zebra"/>
+    </enums>
 
     <enums namespace="GL" start="0x8F90" end="0x8F9F" vendor="ARB">
         <enum value="0x8F90" name="GL_RED_SNORM"/>
@@ -7170,9 +7430,13 @@
         <enum value="0x8F96" name="GL_RGB8_SNORM"/>
         <enum value="0x8F97" name="GL_RGBA8_SNORM"/>
         <enum value="0x8F98" name="GL_R16_SNORM"/>
+        <enum value="0x8F98" name="GL_R16_SNORM_EXT"/>
         <enum value="0x8F99" name="GL_RG16_SNORM"/>
+        <enum value="0x8F99" name="GL_RG16_SNORM_EXT"/>
         <enum value="0x8F9A" name="GL_RGB16_SNORM"/>
+        <enum value="0x8F9A" name="GL_RGB16_SNORM_EXT"/>
         <enum value="0x8F9B" name="GL_RGBA16_SNORM"/>
+        <enum value="0x8F9B" name="GL_RGBA16_SNORM_EXT"/>
         <enum value="0x8F9C" name="GL_SIGNED_NORMALIZED"/>
         <enum value="0x8F9D" name="GL_PRIMITIVE_RESTART"/>
         <enum value="0x8F9E" name="GL_PRIMITIVE_RESTART_INDEX"/>
@@ -7181,14 +7445,17 @@
 
     <enums namespace="GL" start="0x8FA0" end="0x8FBF" vendor="QCOM" comment="For Maurice Ribble, bug 4512">
         <enum value="0x8FA0" name="GL_PERFMON_GLOBAL_MODE_QCOM"/>
-            <unused start="0x8FA1" end="0x8FAF"/>
+            <unused start="0x8FA1" end="0x8FAF" vendor="QCOM"/>
         <enum value="0x8FB0" name="GL_BINNING_CONTROL_HINT_QCOM"/>
         <enum value="0x8FB1" name="GL_CPU_OPTIMIZED_QCOM"/>
         <enum value="0x8FB2" name="GL_GPU_OPTIMIZED_QCOM"/>
         <enum value="0x8FB3" name="GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM"/>
-            <unused start="0x8FB4" end="0x8FBA"/>
+            <unused start="0x8FB4" end="0x8FBA" vendor="QCOM"/>
         <enum value="0x8FBB" name="GL_GPU_DISJOINT_EXT"/>
-            <unused start="0x8FBC" end="0x8FBF"/>
+            <unused start="0x8FBC" vendor="QCOM"/>
+        <enum value="0x8FBD" name="GL_SR8_EXT"/>
+        <enum value="0x8FBE" name="GL_SRG8_EXT"/>
+            <unused start="0x8FBF" vendor="QCOM"/>
     </enums>
 
     <enums namespace="GL" start="0x8FC0" end="0x8FDF" vendor="VIV" comment="For Frido Garritsen, bug 4526">
@@ -7204,8 +7471,11 @@
         <enum value="0x8FE5" name="GL_INT16_VEC2_NV"/>
         <enum value="0x8FE6" name="GL_INT16_VEC3_NV"/>
         <enum value="0x8FE7" name="GL_INT16_VEC4_NV"/>
+        <enum value="0x8FE9" name="GL_INT64_VEC2_ARB"/>
         <enum value="0x8FE9" name="GL_INT64_VEC2_NV"/>
+        <enum value="0x8FEA" name="GL_INT64_VEC3_ARB"/>
         <enum value="0x8FEA" name="GL_INT64_VEC3_NV"/>
+        <enum value="0x8FEB" name="GL_INT64_VEC4_ARB"/>
         <enum value="0x8FEB" name="GL_INT64_VEC4_NV"/>
         <enum value="0x8FEC" name="GL_UNSIGNED_INT8_NV"/>
         <enum value="0x8FED" name="GL_UNSIGNED_INT8_VEC2_NV"/>
@@ -7215,8 +7485,11 @@
         <enum value="0x8FF1" name="GL_UNSIGNED_INT16_VEC2_NV"/>
         <enum value="0x8FF2" name="GL_UNSIGNED_INT16_VEC3_NV"/>
         <enum value="0x8FF3" name="GL_UNSIGNED_INT16_VEC4_NV"/>
+        <enum value="0x8FF5" name="GL_UNSIGNED_INT64_VEC2_ARB"/>
         <enum value="0x8FF5" name="GL_UNSIGNED_INT64_VEC2_NV"/>
+        <enum value="0x8FF6" name="GL_UNSIGNED_INT64_VEC3_ARB"/>
         <enum value="0x8FF6" name="GL_UNSIGNED_INT64_VEC3_NV"/>
+        <enum value="0x8FF7" name="GL_UNSIGNED_INT64_VEC4_ARB"/>
         <enum value="0x8FF7" name="GL_UNSIGNED_INT64_VEC4_NV"/>
         <enum value="0x8FF8" name="GL_FLOAT16_NV"/>
         <enum value="0x8FF9" name="GL_FLOAT16_VEC2_NV"/>
@@ -7228,7 +7501,7 @@
         <enum value="0x8FFD" name="GL_DOUBLE_VEC3_EXT"/>
         <enum value="0x8FFE" name="GL_DOUBLE_VEC4"/>
         <enum value="0x8FFE" name="GL_DOUBLE_VEC4_EXT"/>
-            <unused start="0x8FFF"/>
+            <unused start="0x8FFF" vendor="NV"/>
     </enums>
 
     <enums namespace="GL" start="0x9000" end="0x901F" vendor="AMD" comment="For Bill Licea-Kane">
@@ -7239,27 +7512,33 @@
         <enum value="0x9005" name="GL_TESSELLATION_FACTOR_AMD"/>
         <enum value="0x9006" name="GL_DISCRETE_AMD"/>
         <enum value="0x9007" name="GL_CONTINUOUS_AMD"/>
-            <unused start="0x9008"/>
+            <unused start="0x9008" vendor="AMD"/>
         <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY"/>
         <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY_ARB"/>
         <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x9009" name="GL_TEXTURE_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
         <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_ARB"/>
         <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900A" name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x900B" name="GL_PROXY_TEXTURE_CUBE_MAP_ARRAY"/>
         <enum value="0x900B" name="GL_PROXY_TEXTURE_CUBE_MAP_ARRAY_ARB"/>
         <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY"/>
         <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
         <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900C" name="GL_SAMPLER_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"/>
         <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_ARB"/>
         <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT"/>
+        <enum value="0x900D" name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES"/>
         <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY"/>
         <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
         <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900E" name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"/>
         <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_ARB"/>
         <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x900F" name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x9010" name="GL_ALPHA_SNORM"/>
         <enum value="0x9011" name="GL_LUMINANCE_SNORM"/>
         <enum value="0x9012" name="GL_LUMINANCE_ALPHA_SNORM"/>
@@ -7308,7 +7587,7 @@
         <enum value="0x903A" name="GL_VIDEO_CAPTURE_FIELD_UPPER_HEIGHT_NV"/>
         <enum value="0x903B" name="GL_VIDEO_CAPTURE_FIELD_LOWER_HEIGHT_NV"/>
         <enum value="0x903C" name="GL_VIDEO_CAPTURE_SURFACE_ORIGIN_NV"/>
-            <unused start="0x903D" end="0x9044"/>
+            <unused start="0x903D" end="0x9044" vendor="NV"/>
         <enum value="0x9045" name="GL_TEXTURE_COVERAGE_SAMPLES_NV"/>
         <enum value="0x9046" name="GL_TEXTURE_COLOR_SAMPLES_NV"/>
         <enum value="0x9047" name="GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX"/>
@@ -7328,12 +7607,14 @@
         <enum value="0x9050" name="GL_IMAGE_CUBE_EXT"/>
         <enum value="0x9051" name="GL_IMAGE_BUFFER"/>
         <enum value="0x9051" name="GL_IMAGE_BUFFER_EXT"/>
+        <enum value="0x9051" name="GL_IMAGE_BUFFER_OES"/>
         <enum value="0x9052" name="GL_IMAGE_1D_ARRAY"/>
         <enum value="0x9052" name="GL_IMAGE_1D_ARRAY_EXT"/>
         <enum value="0x9053" name="GL_IMAGE_2D_ARRAY"/>
         <enum value="0x9053" name="GL_IMAGE_2D_ARRAY_EXT"/>
         <enum value="0x9054" name="GL_IMAGE_CUBE_MAP_ARRAY"/>
         <enum value="0x9054" name="GL_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x9054" name="GL_IMAGE_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x9055" name="GL_IMAGE_2D_MULTISAMPLE"/>
         <enum value="0x9055" name="GL_IMAGE_2D_MULTISAMPLE_EXT"/>
         <enum value="0x9056" name="GL_IMAGE_2D_MULTISAMPLE_ARRAY"/>
@@ -7350,12 +7631,14 @@
         <enum value="0x905B" name="GL_INT_IMAGE_CUBE_EXT"/>
         <enum value="0x905C" name="GL_INT_IMAGE_BUFFER"/>
         <enum value="0x905C" name="GL_INT_IMAGE_BUFFER_EXT"/>
+        <enum value="0x905C" name="GL_INT_IMAGE_BUFFER_OES"/>
         <enum value="0x905D" name="GL_INT_IMAGE_1D_ARRAY"/>
         <enum value="0x905D" name="GL_INT_IMAGE_1D_ARRAY_EXT"/>
         <enum value="0x905E" name="GL_INT_IMAGE_2D_ARRAY"/>
         <enum value="0x905E" name="GL_INT_IMAGE_2D_ARRAY_EXT"/>
         <enum value="0x905F" name="GL_INT_IMAGE_CUBE_MAP_ARRAY"/>
         <enum value="0x905F" name="GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x905F" name="GL_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x9060" name="GL_INT_IMAGE_2D_MULTISAMPLE"/>
         <enum value="0x9060" name="GL_INT_IMAGE_2D_MULTISAMPLE_EXT"/>
         <enum value="0x9061" name="GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
@@ -7372,12 +7655,14 @@
         <enum value="0x9066" name="GL_UNSIGNED_INT_IMAGE_CUBE_EXT"/>
         <enum value="0x9067" name="GL_UNSIGNED_INT_IMAGE_BUFFER"/>
         <enum value="0x9067" name="GL_UNSIGNED_INT_IMAGE_BUFFER_EXT"/>
+        <enum value="0x9067" name="GL_UNSIGNED_INT_IMAGE_BUFFER_OES"/>
         <enum value="0x9068" name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY"/>
         <enum value="0x9068" name="GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT"/>
         <enum value="0x9069" name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY"/>
         <enum value="0x9069" name="GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT"/>
         <enum value="0x906A" name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"/>
         <enum value="0x906A" name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT"/>
+        <enum value="0x906A" name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
         <enum value="0x906B" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE"/>
         <enum value="0x906B" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT"/>
         <enum value="0x906C" name="GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY"/>
@@ -7467,17 +7752,20 @@
         <enum value="0x90BD" name="GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV"/>
         <enum value="0x90BE" name="GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV"/>
         <enum value="0x90BF" name="GL_PATH_COVER_DEPTH_FUNC_NV"/>
-            <unused start="0x90C0" end="0x90C6"/>
+            <unused start="0x90C0" end="0x90C6" vendor="NV"/>
         <enum value="0x90C7" name="GL_IMAGE_FORMAT_COMPATIBILITY_TYPE"/>
         <enum value="0x90C8" name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE"/>
         <enum value="0x90C9" name="GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS"/>
         <enum value="0x90CA" name="GL_MAX_VERTEX_IMAGE_UNIFORMS"/>
         <enum value="0x90CB" name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"/>
         <enum value="0x90CB" name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT"/>
+        <enum value="0x90CB" name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES"/>
         <enum value="0x90CC" name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"/>
         <enum value="0x90CC" name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT"/>
+        <enum value="0x90CC" name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES"/>
         <enum value="0x90CD" name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS"/>
         <enum value="0x90CD" name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT"/>
+        <enum value="0x90CD" name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES"/>
         <enum value="0x90CE" name="GL_MAX_FRAGMENT_IMAGE_UNIFORMS"/>
         <enum value="0x90CF" name="GL_MAX_COMBINED_IMAGE_UNIFORMS"/>
         <enum value="0x90D0" name="GL_MAX_DEEP_3D_TEXTURE_WIDTH_HEIGHT_NV"/>
@@ -7489,19 +7777,22 @@
         <enum value="0x90D6" name="GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90D7" name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90D7" name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT"/>
+        <enum value="0x90D7" name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES"/>
         <enum value="0x90D8" name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90D8" name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT"/>
+        <enum value="0x90D8" name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES"/>
         <enum value="0x90D9" name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90D9" name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT"/>
+        <enum value="0x90D9" name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES"/>
         <enum value="0x90DA" name="GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90DB" name="GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90DC" name="GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS"/>
         <enum value="0x90DD" name="GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS"/>
         <enum value="0x90DE" name="GL_MAX_SHADER_STORAGE_BLOCK_SIZE"/>
         <enum value="0x90DF" name="GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT"/>
-            <unused start="0x90E0"/>
+            <unused start="0x90E0" vendor="NV"/>
         <enum value="0x90E1" name="GL_SYNC_X11_FENCE_EXT"/>
-            <unused start="0x90E2" end="0x90E9"/>
+            <unused start="0x90E2" end="0x90E9" vendor="NV"/>
         <enum value="0x90EA" name="GL_DEPTH_STENCIL_TEXTURE_MODE"/>
         <enum value="0x90EB" name="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
         <enum value="0x90EB" name="GL_MAX_COMPUTE_FIXED_GROUP_INVOCATIONS_ARB" alias="GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS"/>
@@ -7512,11 +7803,13 @@
         <enum value="0x90F0" name="GL_COLOR_ATTACHMENT_EXT"/>
         <enum value="0x90F1" name="GL_MULTIVIEW_EXT"/>
         <enum value="0x90F2" name="GL_MAX_MULTIVIEW_BUFFERS_EXT"/>
+        <enum value="0x90F3" name="GL_CONTEXT_ROBUST_ACCESS"/>
         <enum value="0x90F3" name="GL_CONTEXT_ROBUST_ACCESS_EXT"/>
-            <unused start="0x90F4" end="0x90FA"/>
+        <enum value="0x90F3" name="GL_CONTEXT_ROBUST_ACCESS_KHR"/>
+            <unused start="0x90F4" end="0x90FA" vendor="NV"/>
         <enum value="0x90FB" name="GL_COMPUTE_PROGRAM_NV"/>
         <enum value="0x90FC" name="GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV"/>
-            <unused start="0x90FD" end="0x90FF"/>
+            <unused start="0x90FD" end="0x90FF" vendor="NV"/>
     </enums>
 
     <enums namespace="GL" start="0x9100" end="0x912F" vendor="ARB">
@@ -7574,8 +7867,10 @@
         <enum value="0x9122" name="GL_MAX_VERTEX_OUTPUT_COMPONENTS"/>
         <enum value="0x9123" name="GL_MAX_GEOMETRY_INPUT_COMPONENTS"/>
         <enum value="0x9123" name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT"/>
+        <enum value="0x9123" name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES"/>
         <enum value="0x9124" name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"/>
         <enum value="0x9124" name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT"/>
+        <enum value="0x9124" name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES"/>
         <enum value="0x9125" name="GL_MAX_FRAGMENT_INPUT_COMPONENTS"/>
         <enum value="0x9126" name="GL_CONTEXT_PROFILE_MASK"/>
         <enum value="0x9127" name="GL_UNPACK_COMPRESSED_BLOCK_WIDTH"/>
@@ -7592,18 +7887,21 @@
 
     <enums namespace="GL" start="0x9130" end="0x913F" vendor="IMG" comment="Khronos bug 882">
         <enum value="0x9130" name="GL_SGX_PROGRAM_BINARY_IMG"/>
-            <unused start="0x9131" end="0x9132"/>
+            <unused start="0x9131" end="0x9132" vendor="IMG"/>
         <enum value="0x9133" name="GL_RENDERBUFFER_SAMPLES_IMG"/>
         <enum value="0x9134" name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG"/>
         <enum value="0x9135" name="GL_MAX_SAMPLES_IMG"/>
         <enum value="0x9136" name="GL_TEXTURE_SAMPLES_IMG"/>
         <enum value="0x9137" name="GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG"/>
         <enum value="0x9138" name="GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG"/>
-            <unused start="0x9139" end="0x913F"/>
+        <enum value="0x9139" name="GL_CUBIC_IMG"/>
+        <enum value="0x913A" name="GL_CUBIC_MIPMAP_NEAREST_IMG"/>
+        <enum value="0x913B" name="GL_CUBIC_MIPMAP_LINEAR_IMG"/>
+            <unused start="0x913C" end="0x913F" vendor="IMG"/>
     </enums>
 
     <enums namespace="GL" start="0x9140" end="0x923F" vendor="AMD" comment="Khronos bugs 5899, 6004">
-            <unused start="0x9140" end="0x9142"/>
+            <unused start="0x9140" end="0x9142" vendor="AMD"/>
         <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
         <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH_AMD"/>
         <enum value="0x9143" name="GL_MAX_DEBUG_MESSAGE_LENGTH_ARB"/>
@@ -7644,9 +7942,9 @@
         <enum value="0x9154" name="GL_VERTEX_ARRAY_OBJECT_AMD"/>
         <enum value="0x9154" name="GL_VERTEX_ARRAY_OBJECT_EXT"/>
         <enum value="0x9155" name="GL_SAMPLER_OBJECT_AMD"/>
-            <unused start="0x9156" end="0x915F"/>
+            <unused start="0x9156" end="0x915F" vendor="AMD"/>
         <enum value="0x9160" name="GL_EXTERNAL_VIRTUAL_MEMORY_BUFFER_AMD"/>
-            <unused start="0x9161"/>
+            <unused start="0x9161" vendor="AMD"/>
         <enum value="0x9192" name="GL_QUERY_BUFFER"/>
         <enum value="0x9192" name="GL_QUERY_BUFFER_AMD"/>
         <enum value="0x9193" name="GL_QUERY_BUFFER_BINDING"/>
@@ -7654,44 +7952,61 @@
         <enum value="0x9194" name="GL_QUERY_RESULT_NO_WAIT"/>
         <enum value="0x9194" name="GL_QUERY_RESULT_NO_WAIT_AMD"/>
         <enum value="0x9195" name="GL_VIRTUAL_PAGE_SIZE_X_ARB"/>
+        <enum value="0x9195" name="GL_VIRTUAL_PAGE_SIZE_X_EXT"/>
         <enum value="0x9195" name="GL_VIRTUAL_PAGE_SIZE_X_AMD"/>
         <enum value="0x9196" name="GL_VIRTUAL_PAGE_SIZE_Y_ARB"/>
+        <enum value="0x9196" name="GL_VIRTUAL_PAGE_SIZE_Y_EXT"/>
         <enum value="0x9196" name="GL_VIRTUAL_PAGE_SIZE_Y_AMD"/>
         <enum value="0x9197" name="GL_VIRTUAL_PAGE_SIZE_Z_ARB"/>
+        <enum value="0x9197" name="GL_VIRTUAL_PAGE_SIZE_Z_EXT"/>
         <enum value="0x9197" name="GL_VIRTUAL_PAGE_SIZE_Z_AMD"/>
         <enum value="0x9198" name="GL_MAX_SPARSE_TEXTURE_SIZE_ARB"/>
+        <enum value="0x9198" name="GL_MAX_SPARSE_TEXTURE_SIZE_EXT"/>
         <enum value="0x9198" name="GL_MAX_SPARSE_TEXTURE_SIZE_AMD"/>
         <enum value="0x9199" name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB"/>
+        <enum value="0x9199" name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT"/>
         <enum value="0x9199" name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD"/>
-        <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB"/>
         <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS"/>
-        <enum value="0x919B" name="GL_MIN_SPARSE_LEVEL_ARB"/>
+        <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB"/>
+        <enum value="0x919A" name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT"/>
         <enum value="0x919B" name="GL_MIN_SPARSE_LEVEL_AMD"/>
         <enum value="0x919C" name="GL_MIN_LOD_WARNING_AMD"/>
         <enum value="0x919D" name="GL_TEXTURE_BUFFER_OFFSET"/>
         <enum value="0x919D" name="GL_TEXTURE_BUFFER_OFFSET_EXT"/>
+        <enum value="0x919D" name="GL_TEXTURE_BUFFER_OFFSET_OES"/>
         <enum value="0x919E" name="GL_TEXTURE_BUFFER_SIZE"/>
         <enum value="0x919E" name="GL_TEXTURE_BUFFER_SIZE_EXT"/>
+        <enum value="0x919E" name="GL_TEXTURE_BUFFER_SIZE_OES"/>
         <enum value="0x919F" name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"/>
         <enum value="0x919F" name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT"/>
+        <enum value="0x919F" name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES"/>
         <enum value="0x91A0" name="GL_STREAM_RASTERIZATION_AMD"/>
-            <unused start="0x91A1" end="0x91A3"/>
+            <unused start="0x91A1" end="0x91A3" vendor="AMD"/>
         <enum value="0x91A4" name="GL_VERTEX_ELEMENT_SWIZZLE_AMD"/>
         <enum value="0x91A5" name="GL_VERTEX_ID_SWIZZLE_AMD"/>
         <enum value="0x91A6" name="GL_TEXTURE_SPARSE_ARB"/>
+        <enum value="0x91A6" name="GL_TEXTURE_SPARSE_EXT"/>
         <enum value="0x91A7" name="GL_VIRTUAL_PAGE_SIZE_INDEX_ARB"/>
+        <enum value="0x91A7" name="GL_VIRTUAL_PAGE_SIZE_INDEX_EXT"/>
         <enum value="0x91A8" name="GL_NUM_VIRTUAL_PAGE_SIZES_ARB"/>
+        <enum value="0x91A8" name="GL_NUM_VIRTUAL_PAGE_SIZES_EXT"/>
         <enum value="0x91A9" name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB"/>
-            <unused start="0x91AA" end="0x91B8"/>
+        <enum value="0x91A9" name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT"/>
+        <enum value="0x91AA" name="GL_NUM_SPARSE_LEVELS_ARB"/>
+        <enum value="0x91AA" name="GL_NUM_SPARSE_LEVELS_EXT"/>
+            <unused start="0x91AB" end="0x91AF" vendor="AMD"/>
+        <enum value="0x91B0" name="GL_MAX_SHADER_COMPILER_THREADS_ARB"/>
+        <enum value="0x91B1" name="GL_COMPLETION_STATUS_ARB"/>
+            <unused start="0x91B2" end="0x91B8" vendor="AMD"/>
         <enum value="0x91B9" name="GL_COMPUTE_SHADER"/>
-            <unused start="0x91BA"/>
+            <unused start="0x91BA" vendor="AMD"/>
         <enum value="0x91BB" name="GL_MAX_COMPUTE_UNIFORM_BLOCKS"/>
         <enum value="0x91BC" name="GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS"/>
         <enum value="0x91BD" name="GL_MAX_COMPUTE_IMAGE_UNIFORMS"/>
         <enum value="0x91BE" name="GL_MAX_COMPUTE_WORK_GROUP_COUNT"/>
         <enum value="0x91BF" name="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
         <enum value="0x91BF" name="GL_MAX_COMPUTE_FIXED_GROUP_SIZE_ARB" alias="GL_MAX_COMPUTE_WORK_GROUP_SIZE"/>
-            <unused start="0x91C0" end="0x923F"/>
+            <unused start="0x91C0" end="0x923F" vendor="AMD"/>
     </enums>
 
     <enums namespace="GL" start="0x9240" end="0x924F" vendor="WEBGL" comment="Khronos bug 6473,6884">
@@ -7700,17 +8015,20 @@
         <enum value="0x9242" name="GL_CONTEXT_LOST_WEBGL"/>
         <enum value="0x9243" name="GL_UNPACK_COLORSPACE_CONVERSION_WEBGL"/>
         <enum value="0x9244" name="GL_BROWSER_DEFAULT_WEBGL"/>
-            <unused start="0x9245" end="0x924F"/>
+            <unused start="0x9245" end="0x924F" vendor="WEBGL"/>
     </enums>
 
     <enums namespace="GL" start="0x9250" end="0x925F" vendor="DMP" comment="For Eisaku Ohbuchi via email">
         <enum value="0x9250" name="GL_SHADER_BINARY_DMP"/>
-            <unused start="0x9251" end="0x925F"/>
+        <enum value="0x9251" name="GL_SMAPHS30_PROGRAM_BINARY_DMP"/>
+        <enum value="0x9252" name="GL_SMAPHS_PROGRAM_BINARY_DMP"/>
+        <enum value="0x9253" name="GL_DMP_PROGRAM_BINARY_DMP"/>
+            <unused start="0x9254" end="0x925F" vendor="DMP"/>
     </enums>
 
     <enums namespace="GL" start="0x9260" end="0x926F" vendor="FJ" comment="Khronos bug 7486">
         <enum value="0x9260" name="GL_GCCSO_SHADER_BINARY_FJ"/>
-            <unused start="0x9261" end="0x926F"/>
+            <unused start="0x9261" end="0x926F" vendor="FJ"/>
     </enums>
 
     <enums namespace="GL" start="0x9270" end="0x927F" vendor="OES" comment="Khronos bug 7625">
@@ -7734,7 +8052,7 @@
         <enum value="0x9278" name="GL_COMPRESSED_RGBA8_ETC2_EAC_OES"/>
         <enum value="0x9279" name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC"/>
         <enum value="0x9279" name="GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_OES"/>
-            <unused start="0x927A" end="0x927F"/>
+            <unused start="0x927A" end="0x927F" vendor="OES"/>
     </enums>
 
     <enums namespace="GL" start="0x9280" end="0x937F" vendor="NV" comment="Khronos bug 7658">
@@ -7755,36 +8073,47 @@
         <enum value="0x928D" name="GL_DST_OUT_NV"/>
         <enum value="0x928E" name="GL_SRC_ATOP_NV"/>
         <enum value="0x928F" name="GL_DST_ATOP_NV"/>
-            <unused start="0x9290"/>
+            <unused start="0x9290" vendor="NV"/>
         <enum value="0x9291" name="GL_PLUS_NV"/>
         <enum value="0x9292" name="GL_PLUS_DARKER_NV"/>
-            <unused start="0x9293"/>
+            <unused start="0x9293" vendor="NV"/>
+        <enum value="0x9294" name="GL_MULTIPLY"/>
         <enum value="0x9294" name="GL_MULTIPLY_KHR"/>
         <enum value="0x9294" name="GL_MULTIPLY_NV"/>
+        <enum value="0x9295" name="GL_SCREEN"/>
         <enum value="0x9295" name="GL_SCREEN_KHR"/>
         <enum value="0x9295" name="GL_SCREEN_NV"/>
+        <enum value="0x9296" name="GL_OVERLAY"/>
         <enum value="0x9296" name="GL_OVERLAY_KHR"/>
         <enum value="0x9296" name="GL_OVERLAY_NV"/>
+        <enum value="0x9297" name="GL_DARKEN"/>
         <enum value="0x9297" name="GL_DARKEN_KHR"/>
         <enum value="0x9297" name="GL_DARKEN_NV"/>
+        <enum value="0x9298" name="GL_LIGHTEN"/>
         <enum value="0x9298" name="GL_LIGHTEN_KHR"/>
         <enum value="0x9298" name="GL_LIGHTEN_NV"/>
+        <enum value="0x9299" name="GL_COLORDODGE"/>
         <enum value="0x9299" name="GL_COLORDODGE_KHR"/>
         <enum value="0x9299" name="GL_COLORDODGE_NV"/>
+        <enum value="0x929A" name="GL_COLORBURN"/>
         <enum value="0x929A" name="GL_COLORBURN_KHR"/>
         <enum value="0x929A" name="GL_COLORBURN_NV"/>
+        <enum value="0x929B" name="GL_HARDLIGHT"/>
         <enum value="0x929B" name="GL_HARDLIGHT_KHR"/>
         <enum value="0x929B" name="GL_HARDLIGHT_NV"/>
+        <enum value="0x929C" name="GL_SOFTLIGHT"/>
         <enum value="0x929C" name="GL_SOFTLIGHT_KHR"/>
         <enum value="0x929C" name="GL_SOFTLIGHT_NV"/>
-            <unused start="0x929D"/>
+            <unused start="0x929D" vendor="NV"/>
+        <enum value="0x929E" name="GL_DIFFERENCE"/>
         <enum value="0x929E" name="GL_DIFFERENCE_KHR"/>
         <enum value="0x929E" name="GL_DIFFERENCE_NV"/>
         <enum value="0x929F" name="GL_MINUS_NV"/>
+        <enum value="0x92A0" name="GL_EXCLUSION"/>
         <enum value="0x92A0" name="GL_EXCLUSION_KHR"/>
         <enum value="0x92A0" name="GL_EXCLUSION_NV"/>
         <enum value="0x92A1" name="GL_CONTRAST_NV"/>
-            <unused start="0x92A2"/>
+            <unused start="0x92A2" vendor="NV"/>
         <enum value="0x92A3" name="GL_INVERT_RGB_NV"/>
         <enum value="0x92A4" name="GL_LINEARDODGE_NV"/>
         <enum value="0x92A5" name="GL_LINEARBURN_NV"/>
@@ -7792,22 +8121,29 @@
         <enum value="0x92A7" name="GL_LINEARLIGHT_NV"/>
         <enum value="0x92A8" name="GL_PINLIGHT_NV"/>
         <enum value="0x92A9" name="GL_HARDMIX_NV"/>
-            <unused start="0x92AA" end="0x92AC"/>
+            <unused start="0x92AA" end="0x92AC" vendor="NV"/>
+        <enum value="0x92AD" name="GL_HSL_HUE"/>
         <enum value="0x92AD" name="GL_HSL_HUE_KHR"/>
         <enum value="0x92AD" name="GL_HSL_HUE_NV"/>
+        <enum value="0x92AE" name="GL_HSL_SATURATION"/>
         <enum value="0x92AE" name="GL_HSL_SATURATION_KHR"/>
         <enum value="0x92AE" name="GL_HSL_SATURATION_NV"/>
+        <enum value="0x92AF" name="GL_HSL_COLOR"/>
         <enum value="0x92AF" name="GL_HSL_COLOR_KHR"/>
         <enum value="0x92AF" name="GL_HSL_COLOR_NV"/>
+        <enum value="0x92B0" name="GL_HSL_LUMINOSITY"/>
         <enum value="0x92B0" name="GL_HSL_LUMINOSITY_KHR"/>
         <enum value="0x92B0" name="GL_HSL_LUMINOSITY_NV"/>
         <enum value="0x92B1" name="GL_PLUS_CLAMPED_NV"/>
         <enum value="0x92B2" name="GL_PLUS_CLAMPED_ALPHA_NV"/>
         <enum value="0x92B3" name="GL_MINUS_CLAMPED_NV"/>
         <enum value="0x92B4" name="GL_INVERT_OVG_NV"/>
-            <unused start="0x92B5" end="0x92BD"/>
+            <unused start="0x92B5" end="0x92BD" vendor="NV"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX_ARB"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX"/>
         <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX_EXT"/>
-            <unused start="0x92BF"/>
+        <enum value="0x92BE" name="GL_PRIMITIVE_BOUNDING_BOX_OES"/>
+            <unused start="0x92BF" vendor="NV"/>
         <enum value="0x92C0" name="GL_ATOMIC_COUNTER_BUFFER"/>
         <enum value="0x92C1" name="GL_ATOMIC_COUNTER_BUFFER_BINDING"/>
         <enum value="0x92C2" name="GL_ATOMIC_COUNTER_BUFFER_START"/>
@@ -7823,19 +8159,25 @@
         <enum value="0x92CC" name="GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS"/>
         <enum value="0x92CD" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"/>
         <enum value="0x92CD" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT"/>
+        <enum value="0x92CD" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES"/>
         <enum value="0x92CE" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"/>
         <enum value="0x92CE" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT"/>
+        <enum value="0x92CE" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES"/>
         <enum value="0x92CF" name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"/>
         <enum value="0x92CF" name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT"/>
+        <enum value="0x92CF" name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES"/>
         <enum value="0x92D0" name="GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS"/>
         <enum value="0x92D1" name="GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS"/>
         <enum value="0x92D2" name="GL_MAX_VERTEX_ATOMIC_COUNTERS"/>
         <enum value="0x92D3" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"/>
         <enum value="0x92D3" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT"/>
+        <enum value="0x92D3" name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES"/>
         <enum value="0x92D4" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"/>
         <enum value="0x92D4" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT"/>
+        <enum value="0x92D4" name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES"/>
         <enum value="0x92D5" name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS"/>
         <enum value="0x92D5" name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT"/>
+        <enum value="0x92D5" name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES"/>
         <enum value="0x92D6" name="GL_MAX_FRAGMENT_ATOMIC_COUNTERS"/>
         <enum value="0x92D7" name="GL_MAX_COMBINED_ATOMIC_COUNTERS"/>
         <enum value="0x92D8" name="GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE"/>
@@ -7843,7 +8185,9 @@
         <enum value="0x92DA" name="GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX"/>
         <enum value="0x92DB" name="GL_UNSIGNED_INT_ATOMIC_COUNTER"/>
         <enum value="0x92DC" name="GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS"/>
-            <unused start="0x92DC" end="0x92DF"/>
+        <enum value="0x92DD" name="GL_FRAGMENT_COVERAGE_TO_COLOR_NV"/>
+        <enum value="0x92DE" name="GL_FRAGMENT_COVERAGE_COLOR_NV"/>
+            <unused start="0x92DF" end="0x92DF" vendor="NV"/>
         <enum value="0x92E0" name="GL_DEBUG_OUTPUT"/>
         <enum value="0x92E0" name="GL_DEBUG_OUTPUT_KHR"/>
         <enum value="0x92E1" name="GL_UNIFORM"/>
@@ -7854,6 +8198,7 @@
         <enum value="0x92E6" name="GL_SHADER_STORAGE_BLOCK"/>
         <enum value="0x92E7" name="GL_IS_PER_PATCH"/>
         <enum value="0x92E7" name="GL_IS_PER_PATCH_EXT"/>
+        <enum value="0x92E7" name="GL_IS_PER_PATCH_OES"/>
         <enum value="0x92E8" name="GL_VERTEX_SUBROUTINE"/>
         <enum value="0x92E9" name="GL_TESS_CONTROL_SUBROUTINE"/>
         <enum value="0x92EA" name="GL_TESS_EVALUATION_SUBROUTINE"/>
@@ -7887,46 +8232,111 @@
         <enum value="0x9306" name="GL_REFERENCED_BY_VERTEX_SHADER"/>
         <enum value="0x9307" name="GL_REFERENCED_BY_TESS_CONTROL_SHADER"/>
         <enum value="0x9307" name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT"/>
+        <enum value="0x9307" name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES"/>
         <enum value="0x9308" name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
         <enum value="0x9308" name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT"/>
+        <enum value="0x9308" name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES"/>
         <enum value="0x9309" name="GL_REFERENCED_BY_GEOMETRY_SHADER"/>
         <enum value="0x9309" name="GL_REFERENCED_BY_GEOMETRY_SHADER_EXT"/>
+        <enum value="0x9309" name="GL_REFERENCED_BY_GEOMETRY_SHADER_OES"/>
         <enum value="0x930A" name="GL_REFERENCED_BY_FRAGMENT_SHADER"/>
         <enum value="0x930B" name="GL_REFERENCED_BY_COMPUTE_SHADER"/>
         <enum value="0x930C" name="GL_TOP_LEVEL_ARRAY_SIZE"/>
         <enum value="0x930D" name="GL_TOP_LEVEL_ARRAY_STRIDE"/>
         <enum value="0x930E" name="GL_LOCATION"/>
         <enum value="0x930F" name="GL_LOCATION_INDEX"/>
+        <enum value="0x930F" name="GL_LOCATION_INDEX_EXT"/>
         <enum value="0x9310" name="GL_FRAMEBUFFER_DEFAULT_WIDTH"/>
         <enum value="0x9311" name="GL_FRAMEBUFFER_DEFAULT_HEIGHT"/>
         <enum value="0x9312" name="GL_FRAMEBUFFER_DEFAULT_LAYERS"/>
         <enum value="0x9312" name="GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT"/>
+        <enum value="0x9312" name="GL_FRAMEBUFFER_DEFAULT_LAYERS_OES"/>
         <enum value="0x9313" name="GL_FRAMEBUFFER_DEFAULT_SAMPLES"/>
         <enum value="0x9314" name="GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS"/>
         <enum value="0x9315" name="GL_MAX_FRAMEBUFFER_WIDTH"/>
         <enum value="0x9316" name="GL_MAX_FRAMEBUFFER_HEIGHT"/>
         <enum value="0x9317" name="GL_MAX_FRAMEBUFFER_LAYERS"/>
         <enum value="0x9317" name="GL_MAX_FRAMEBUFFER_LAYERS_EXT"/>
+        <enum value="0x9317" name="GL_MAX_FRAMEBUFFER_LAYERS_OES"/>
         <enum value="0x9318" name="GL_MAX_FRAMEBUFFER_SAMPLES"/>
-            <unused start="0x9319" end="0x9338"/>
+            <unused start="0x9319" end="0x9326" vendor="NV"/>
+        <enum value="0x9327" name="GL_RASTER_MULTISAMPLE_EXT"/>
+        <enum value="0x9328" name="GL_RASTER_SAMPLES_EXT"/>
+        <enum value="0x9329" name="GL_MAX_RASTER_SAMPLES_EXT"/>
+        <enum value="0x932A" name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+        <enum value="0x932B" name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+        <enum value="0x932C" name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+        <enum value="0x932D" name="GL_DEPTH_SAMPLES_NV"/>
+        <enum value="0x932E" name="GL_STENCIL_SAMPLES_NV"/>
+        <enum value="0x932F" name="GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV"/>
+        <enum value="0x9330" name="GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV"/>
+        <enum value="0x9331" name="GL_COVERAGE_MODULATION_TABLE_NV"/>
+        <enum value="0x9332" name="GL_COVERAGE_MODULATION_NV"/>
+        <enum value="0x9333" name="GL_COVERAGE_MODULATION_TABLE_SIZE_NV"/>
+            <unused start="0x9334" end="0x9338" vendor="NV"/>
         <enum value="0x9339" name="GL_WARP_SIZE_NV"/>
         <enum value="0x933A" name="GL_WARPS_PER_SM_NV"/>
         <enum value="0x933B" name="GL_SM_COUNT_NV"/>
-            <unused start="0x933C" end="0x9343"/>
+        <enum value="0x933C" name="GL_FILL_RECTANGLE_NV"/>
+        <enum value="0x933D" name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB"/>
+        <enum value="0x933D" name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV"/>
+        <enum value="0x933E" name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB"/>
+        <enum value="0x933E" name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV"/>
+        <enum value="0x933F" name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB"/>
+        <enum value="0x933F" name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV"/>
+        <enum value="0x9340" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB"/>
+        <enum value="0x9340" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV"/>
+        <enum value="0x9341" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB"/>
+        <enum value="0x9341" name="GL_PROGRAMMABLE_SAMPLE_LOCATION_NV"/>
+        <enum value="0x9342" name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB"/>
+        <enum value="0x9342" name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV"/>
+        <enum value="0x9343" name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB"/>
+        <enum value="0x9343" name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV"/>
         <enum value="0x9344" name="GL_MAX_COMPUTE_VARIABLE_GROUP_INVOCATIONS_ARB"/>
         <enum value="0x9345" name="GL_MAX_COMPUTE_VARIABLE_GROUP_SIZE_ARB"/>
-            <unused start="0x9346" end="0x9349"/>
+        <enum value="0x9346" name="GL_CONSERVATIVE_RASTERIZATION_NV"/>
+        <enum value="0x9347" name="GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV"/>
+        <enum value="0x9348" name="GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV"/>
+        <enum value="0x9349" name="GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV"/>
         <enum value="0x934A" name="GL_LOCATION_COMPONENT"/>
         <enum value="0x934B" name="GL_TRANSFORM_FEEDBACK_BUFFER_INDEX"/>
         <enum value="0x934C" name="GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE"/>
-            <unused start="0x934D" end="0x9364"/>
+            <unused start="0x934D" end="0x935B" vendor="NV"/>
+        <enum value="0x935C" name="GL_CLIP_ORIGIN"/>
+        <enum value="0x935D" name="GL_CLIP_DEPTH_MODE"/>
+        <enum value="0x935E" name="GL_NEGATIVE_ONE_TO_ONE"/>
+        <enum value="0x935F" name="GL_ZERO_TO_ONE"/>
+            <unused start="0x9360" end="0x9364" vendor="NV"/>
         <enum value="0x9365" name="GL_CLEAR_TEXTURE"/>
-            <unused start="0x9366" end="0x937F"/>
+        <enum value="0x9366" name="GL_TEXTURE_REDUCTION_MODE_ARB"/>
+        <enum value="0x9367" name="GL_WEIGHTED_AVERAGE_ARB"/>
+        <enum value="0x9368" name="GL_FONT_GLYPHS_AVAILABLE_NV"/>
+        <enum value="0x9369" name="GL_FONT_TARGET_UNAVAILABLE_NV"/>
+        <enum value="0x936A" name="GL_FONT_UNAVAILABLE_NV"/>
+        <enum value="0x936B" name="GL_FONT_UNINTELLIGIBLE_NV"/>
+        <enum value="0x936C" name="GL_STANDARD_FONT_FORMAT_NV"/>
+        <enum value="0x936D" name="GL_FRAGMENT_INPUT_NV"/>
+        <enum value="0x936E" name="GL_UNIFORM_BUFFER_UNIFIED_NV"/>
+        <enum value="0x936F" name="GL_UNIFORM_BUFFER_ADDRESS_NV"/>
+        <enum value="0x9370" name="GL_UNIFORM_BUFFER_LENGTH_NV"/>
+        <enum value="0x9371" name="GL_MULTISAMPLES_NV"/>
+        <enum value="0x9372" name="GL_SUPERSAMPLE_SCALE_X_NV"/>
+        <enum value="0x9373" name="GL_SUPERSAMPLE_SCALE_Y_NV"/>
+        <enum value="0x9374" name="GL_CONFORMANT_NV"/>
+            <unused start="0x9375" end="0x9378" vendor="NV"/>
+        <enum value="0x9379" name="GL_CONSERVATIVE_RASTER_DILATE_NV"/>
+        <enum value="0x937A" name="GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV"/>
+        <enum value="0x937B" name="GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV"/>
+            <unused start="0x937C" end="0x937F" vendor="NV"/>
     </enums>
 
     <enums namespace="GL" start="0x9380" end="0x939F" vendor="ARB">
         <enum value="0x9380" name="GL_NUM_SAMPLE_COUNTS"/>
-            <unused start="0x9381" end="0x939F"/>
+        <enum value="0x9381" name="GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB"/>
+        <enum value="0x9381" name="GL_MULTISAMPLE_LINE_WIDTH_RANGE"/>
+        <enum value="0x9382" name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB"/>
+        <enum value="0x9382" name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY"/>
+            <unused start="0x9383" end="0x939F" vendor="ARB"/>
     </enums>
 
     <enums namespace="GL" start="0x93A0" end="0x93AF" vendor="ANGLE" comment="Khronos bug 8100">
@@ -7935,27 +8345,41 @@
         <enum value="0x93A2" name="GL_TEXTURE_USAGE_ANGLE"/>
         <enum value="0x93A3" name="GL_FRAMEBUFFER_ATTACHMENT_ANGLE"/>
         <enum value="0x93A4" name="GL_PACK_REVERSE_ROW_ORDER_ANGLE"/>
-            <unused start="0x93A5"/>
+            <unused start="0x93A5" vendor="ANGLE"/>
         <enum value="0x93A6" name="GL_PROGRAM_BINARY_ANGLE"/>
-            <unused start="0x93A7" end="0x93AF"/>
+            <unused start="0x93A7" end="0x93AF" vendor="ANGLE"/>
     </enums>
 
     <enums namespace="GL" start="0x93B0" end="0x93EF" vendor="OES" comment="Khronos bug 8853">
+        <enum value="0x93B0" name="GL_COMPRESSED_RGBA_ASTC_4x4"/>
         <enum value="0x93B0" name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
+        <enum value="0x93B1" name="GL_COMPRESSED_RGBA_ASTC_5x4"/>
         <enum value="0x93B1" name="GL_COMPRESSED_RGBA_ASTC_5x4_KHR"/>
+        <enum value="0x93B2" name="GL_COMPRESSED_RGBA_ASTC_5x5"/>
         <enum value="0x93B2" name="GL_COMPRESSED_RGBA_ASTC_5x5_KHR"/>
+        <enum value="0x93B3" name="GL_COMPRESSED_RGBA_ASTC_6x5"/>
         <enum value="0x93B3" name="GL_COMPRESSED_RGBA_ASTC_6x5_KHR"/>
+        <enum value="0x93B4" name="GL_COMPRESSED_RGBA_ASTC_6x6"/>
         <enum value="0x93B4" name="GL_COMPRESSED_RGBA_ASTC_6x6_KHR"/>
+        <enum value="0x93B5" name="GL_COMPRESSED_RGBA_ASTC_8x5"/>
         <enum value="0x93B5" name="GL_COMPRESSED_RGBA_ASTC_8x5_KHR"/>
+        <enum value="0x93B6" name="GL_COMPRESSED_RGBA_ASTC_8x6"/>
         <enum value="0x93B6" name="GL_COMPRESSED_RGBA_ASTC_8x6_KHR"/>
+        <enum value="0x93B7" name="GL_COMPRESSED_RGBA_ASTC_8x8"/>
         <enum value="0x93B7" name="GL_COMPRESSED_RGBA_ASTC_8x8_KHR"/>
+        <enum value="0x93B8" name="GL_COMPRESSED_RGBA_ASTC_10x5"/>
         <enum value="0x93B8" name="GL_COMPRESSED_RGBA_ASTC_10x5_KHR"/>
+        <enum value="0x93B9" name="GL_COMPRESSED_RGBA_ASTC_10x6"/>
         <enum value="0x93B9" name="GL_COMPRESSED_RGBA_ASTC_10x6_KHR"/>
+        <enum value="0x93BA" name="GL_COMPRESSED_RGBA_ASTC_10x8"/>
         <enum value="0x93BA" name="GL_COMPRESSED_RGBA_ASTC_10x8_KHR"/>
+        <enum value="0x93BB" name="GL_COMPRESSED_RGBA_ASTC_10x10"/>
         <enum value="0x93BB" name="GL_COMPRESSED_RGBA_ASTC_10x10_KHR"/>
+        <enum value="0x93BC" name="GL_COMPRESSED_RGBA_ASTC_12x10"/>
         <enum value="0x93BC" name="GL_COMPRESSED_RGBA_ASTC_12x10_KHR"/>
+        <enum value="0x93BD" name="GL_COMPRESSED_RGBA_ASTC_12x12"/>
         <enum value="0x93BD" name="GL_COMPRESSED_RGBA_ASTC_12x12_KHR"/>
-            <unused start="0x93BE" end="0x93BF"/>
+            <unused start="0x93BE" end="0x93BF" vendor="OES"/>
         <enum value="0x93C0" name="GL_COMPRESSED_RGBA_ASTC_3x3x3_OES"/>
         <enum value="0x93C1" name="GL_COMPRESSED_RGBA_ASTC_4x3x3_OES"/>
         <enum value="0x93C2" name="GL_COMPRESSED_RGBA_ASTC_4x4x3_OES"/>
@@ -7966,22 +8390,36 @@
         <enum value="0x93C7" name="GL_COMPRESSED_RGBA_ASTC_6x5x5_OES"/>
         <enum value="0x93C8" name="GL_COMPRESSED_RGBA_ASTC_6x6x5_OES"/>
         <enum value="0x93C9" name="GL_COMPRESSED_RGBA_ASTC_6x6x6_OES"/>
-            <unused start="0x93CA" end="0x93CF"/>
+            <unused start="0x93CA" end="0x93CF" vendor="OES"/>
+        <enum value="0x93D0" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4"/>
         <enum value="0x93D0" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR"/>
+        <enum value="0x93D1" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4"/>
         <enum value="0x93D1" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR"/>
+        <enum value="0x93D2" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5"/>
         <enum value="0x93D2" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR"/>
+        <enum value="0x93D3" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5"/>
         <enum value="0x93D3" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR"/>
+        <enum value="0x93D4" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6"/>
         <enum value="0x93D4" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR"/>
+        <enum value="0x93D5" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5"/>
         <enum value="0x93D5" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR"/>
+        <enum value="0x93D6" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6"/>
         <enum value="0x93D6" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR"/>
+        <enum value="0x93D7" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8"/>
         <enum value="0x93D7" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR"/>
+        <enum value="0x93D8" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5"/>
         <enum value="0x93D8" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR"/>
+        <enum value="0x93D9" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6"/>
         <enum value="0x93D9" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR"/>
+        <enum value="0x93DA" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8"/>
         <enum value="0x93DA" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR"/>
+        <enum value="0x93DB" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10"/>
         <enum value="0x93DB" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR"/>
+        <enum value="0x93DC" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10"/>
         <enum value="0x93DC" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR"/>
+        <enum value="0x93DD" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12"/>
         <enum value="0x93DD" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"/>
-            <unused start="0x93DE" end="0x93DF"/>
+            <unused start="0x93DE" end="0x93DF" vendor="OES"/>
         <enum value="0x93E0" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES"/>
         <enum value="0x93E1" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES"/>
         <enum value="0x93E2" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES"/>
@@ -7992,13 +8430,13 @@
         <enum value="0x93E7" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES"/>
         <enum value="0x93E8" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES"/>
         <enum value="0x93E9" name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES"/>
-            <unused start="0x93EA" end="0x93EF"/>
+            <unused start="0x93EA" end="0x93EF" vendor="OES"/>
     </enums>
 
     <enums namespace="GL" start="0x93F0" end="0x94EF" vendor="APPLE" comment="Khronos bug 10233">
         <enum value="0x93F0" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG"/>
         <enum value="0x93F1" name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG"/>
-            <unused start="0x93F2" end="0x94EF"/>
+            <unused start="0x93F2" end="0x94EF" vendor="APPLE"/>
     </enums>
 
     <enums namespace="GL" start="0x94F0" end="0x950F" vendor="INTEL" comment="Khronos bug 11345">
@@ -8008,7 +8446,7 @@
         <enum value="0x94F3" name="GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL"/>
         <enum value="0x94F4" name="GL_PERFQUERY_COUNTER_RAW_INTEL"/>
         <enum value="0x94F5" name="GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL"/>
-            <unused start="0x94F6" end="0x94F7"/>
+            <unused start="0x94F6" end="0x94F7" vendor="INTEL"/>
         <enum value="0x94F8" name="GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL"/>
         <enum value="0x94F9" name="GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL"/>
         <enum value="0x94FA" name="GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL"/>
@@ -8018,11 +8456,32 @@
         <enum value="0x94FE" name="GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL"/>
         <enum value="0x94FF" name="GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL"/>
         <enum value="0x9500" name="GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL"/>
-            <unused start="0x9501" end="0x950F"/>
+            <unused start="0x9501" end="0x950F" vendor="INTEL"/>
     </enums>
 
     <enums namespace="GL" start="0x9510" end="0x952F" vendor="Broadcom" comment="Khronos bug 12203">
-            <unused start="0x9510" end="0x952F"/>
+            <unused start="0x9510" end="0x952F" vendor="Broadcom"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9530" end="0x962F" vendor="NV" comment="Khronos bug 12977">
+            <unused start="0x9530" end="0x962F" vendor="NV"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9630" end="0x963F" vendor="Oculus" comment="Email from Cass Everitt">
+        <enum value="0x9630" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"/>
+        <enum value="0x9631" name="GL_MAX_VIEWS_OVR"/>
+        <enum value="0x9632" name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"/>
+            <unused start="0x9633" end="0x963F" vendor="Oculus"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9640" end="0x964F" vendor="Mediatek" comment="Khronos bug 14294">
+        <enum value="0x9640" name="GL_GS_SHADER_BINARY_MTK"/>
+        <enum value="0x9641" name="GL_GS_PROGRAM_BINARY_MTK"/>
+            <unused start="0x9642" end="0x964F" vendor="Mediatek"/>
+    </enums>
+
+    <enums namespace="GL" start="0x9650" end="0x968F" vendor="IMG" comment="Khronos bug 14977">
+            <unused start="0x9650" end="0x968F" vendor="IMG"/>
     </enums>
 
 <!-- Enums reservable for future use. To reserve a new range, allocate one
@@ -8034,8 +8493,8 @@
      file) File requests in the Khronos Bugzilla, OpenGL project, Registry
      component. -->
 
-    <enums namespace="GL" start="0x9530" end="99999" vendor="ARB" comment="RESERVED FOR FUTURE ALLOCATIONS BY KHRONOS">
-        <unused start="0x9530" end="99999"/>
+    <enums namespace="GL" start="0x9690" end="99999" vendor="ARB" comment="RESERVED FOR FUTURE ALLOCATIONS BY KHRONOS">
+        <unused start="0x9690" end="99999" comment="RESERVED"/>
     </enums>
 
 <!-- Historical large block allocations, all unused except (in older days) by IBM -->
@@ -8205,6 +8664,9 @@
             <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>ref</name></param>
         </command>
         <command>
+            <proto>void <name>glApplyFramebufferAttachmentCMAAINTEL</name></proto>
+        </command>
+        <command>
             <proto>void <name>glApplyTextureEXT</name></proto>
             <param group="LightTextureModeEXT"><ptype>GLenum</ptype> <name>mode</name></param>
         </command>
@@ -8464,6 +8926,14 @@
             <param>const <ptype>GLchar</ptype> *<name>name</name></param>
         </command>
         <command>
+            <proto>void <name>glBindFragDataLocationIndexedEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLuint</ptype> <name>colorNumber</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glBindFragDataLocationIndexed"/>
+        </command>
+        <command>
             <proto>void <name>glBindFragmentShaderATI</name></proto>
             <param><ptype>GLuint</ptype> <name>id</name></param>
         </command>
@@ -8599,6 +9069,11 @@
             <glx type="render" opcode="4117"/>
         </command>
         <command>
+            <proto>void <name>glBindTextureUnit</name></proto>
+            <param><ptype>GLuint</ptype> <name>unit</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
             <proto><ptype>GLuint</ptype> <name>glBindTextureUnitParameterEXT</name></proto>
             <param group="TextureUnit"><ptype>GLenum</ptype> <name>unit</name></param>
             <param group="VertexShaderTextureUnitParameter"><ptype>GLenum</ptype> <name>value</name></param>
@@ -8751,10 +9226,15 @@
             <param len="COMPSIZE(width,height)">const <ptype>GLubyte</ptype> *<name>bitmap</name></param>
         </command>
         <command>
-            <proto>void <name>glBlendBarrierNV</name></proto>
+            <proto>void <name>glBlendBarrier</name></proto>
         </command>
         <command>
             <proto>void <name>glBlendBarrierKHR</name></proto>
+            <alias name="glBlendBarrier"/>
+        </command>
+        <command>
+            <proto>void <name>glBlendBarrierNV</name></proto>
+            <alias name="glBlendBarrier"/>
         </command>
         <command>
             <proto>void <name>glBlendColor</name></proto>
@@ -8847,18 +9327,31 @@
             <alias name="glBlendEquationSeparatei"/>
         </command>
         <command>
+            <proto>void <name>glBlendEquationSeparateiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>modeRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>modeAlpha</name></param>
+            <alias name="glBlendEquationSeparatei"/>
+        </command>
+        <command>
             <proto>void <name>glBlendEquationi</name></proto>
             <param><ptype>GLuint</ptype> <name>buf</name></param>
             <param><ptype>GLenum</ptype> <name>mode</name></param>
         </command>
         <command>
+            <proto>void <name>glBlendEquationiARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glBlendEquationi"/>
+        </command>
+        <command>
             <proto>void <name>glBlendEquationiEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buf</name></param>
             <param><ptype>GLenum</ptype> <name>mode</name></param>
             <alias name="glBlendEquationi"/>
         </command>
         <command>
-            <proto>void <name>glBlendEquationiARB</name></proto>
+            <proto>void <name>glBlendEquationiOES</name></proto>
             <param><ptype>GLuint</ptype> <name>buf</name></param>
             <param><ptype>GLenum</ptype> <name>mode</name></param>
             <alias name="glBlendEquationi"/>
@@ -8945,6 +9438,15 @@
             <alias name="glBlendFuncSeparatei"/>
         </command>
         <command>
+            <proto>void <name>glBlendFuncSeparateiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>srcRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>dstRGB</name></param>
+            <param><ptype>GLenum</ptype> <name>srcAlpha</name></param>
+            <param><ptype>GLenum</ptype> <name>dstAlpha</name></param>
+            <alias name="glBlendFuncSeparatei"/>
+        </command>
+        <command>
             <proto>void <name>glBlendFunci</name></proto>
             <param><ptype>GLuint</ptype> <name>buf</name></param>
             <param><ptype>GLenum</ptype> <name>src</name></param>
@@ -8965,6 +9467,13 @@
             <alias name="glBlendFunci"/>
         </command>
         <command>
+            <proto>void <name>glBlendFunciOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>buf</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+            <param><ptype>GLenum</ptype> <name>dst</name></param>
+            <alias name="glBlendFunci"/>
+        </command>
+        <command>
             <proto>void <name>glBlendParameteriNV</name></proto>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
             <param><ptype>GLint</ptype> <name>value</name></param>
@@ -9026,6 +9535,21 @@
             <alias name="glBlitFramebuffer"/>
         </command>
         <command>
+            <proto>void <name>glBlitNamedFramebuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>readFramebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>drawFramebuffer</name></param>
+            <param><ptype>GLint</ptype> <name>srcX0</name></param>
+            <param><ptype>GLint</ptype> <name>srcY0</name></param>
+            <param><ptype>GLint</ptype> <name>srcX1</name></param>
+            <param><ptype>GLint</ptype> <name>srcY1</name></param>
+            <param><ptype>GLint</ptype> <name>dstX0</name></param>
+            <param><ptype>GLint</ptype> <name>dstY0</name></param>
+            <param><ptype>GLint</ptype> <name>dstX1</name></param>
+            <param><ptype>GLint</ptype> <name>dstY1</name></param>
+            <param><ptype>GLbitfield</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>filter</name></param>
+        </command>
+        <command>
             <proto>void <name>glBufferAddressRangeNV</name></proto>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
@@ -9048,6 +9572,13 @@
             <alias name="glBufferData"/>
         </command>
         <command>
+            <proto>void <name>glBufferPageCommitmentARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
             <proto>void <name>glBufferParameteriAPPLE</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
@@ -9061,6 +9592,14 @@
             <param><ptype>GLbitfield</ptype> <name>flags</name></param>
         </command>
         <command>
+            <proto>void <name>glBufferStorageEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <alias name="glBufferStorage"/>
+        </command>
+        <command>
             <proto>void <name>glBufferSubData</name></proto>
             <param group="BufferTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
@@ -9076,6 +9615,10 @@
             <alias name="glBufferSubData"/>
         </command>
         <command>
+            <proto>void <name>glCallCommandListNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+        </command>
+        <command>
             <proto>void <name>glCallList</name></proto>
             <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
             <glx type="render" opcode="1"/>
@@ -9103,6 +9646,11 @@
             <param><ptype>GLenum</ptype> <name>target</name></param>
         </command>
         <command>
+            <proto><ptype>GLenum</ptype> <name>glCheckNamedFramebufferStatus</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+        </command>
+        <command>
             <proto group="FramebufferStatus"><ptype>GLenum</ptype> <name>glCheckNamedFramebufferStatusEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -9255,6 +9803,14 @@
             <glx type="render" opcode="129"/>
         </command>
         <command>
+            <proto>void <name>glClearNamedBufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glClearNamedBufferDataEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLenum</ptype> <name>internalformat</name></param>
@@ -9263,6 +9819,16 @@
             <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
         </command>
         <command>
+            <proto>void <name>glClearNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glClearNamedBufferSubDataEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLenum</ptype> <name>internalformat</name></param>
@@ -9273,6 +9839,35 @@
             <param len="COMPSIZE(format,type)">const void *<name>data</name></param>
         </command>
         <command>
+            <proto>void <name>glClearNamedFramebufferfi</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param><ptype>GLfloat</ptype> <name>depth</name></param>
+            <param><ptype>GLint</ptype> <name>stencil</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param>const <ptype>GLint</ptype> *<name>value</name></param>
+        </command>
+        <command>
+            <proto>void <name>glClearNamedFramebufferuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buffer</name></param>
+            <param><ptype>GLint</ptype> <name>drawbuffer</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glClearStencil</name></proto>
             <param group="StencilValue"><ptype>GLint</ptype> <name>s</name></param>
             <glx type="render" opcode="131"/>
@@ -9330,6 +9925,11 @@
             <alias name="glClientWaitSync"/>
         </command>
         <command>
+            <proto>void <name>glClipControl</name></proto>
+            <param><ptype>GLenum</ptype> <name>origin</name></param>
+            <param><ptype>GLenum</ptype> <name>depth</name></param>
+        </command>
+        <command>
             <proto>void <name>glClipPlane</name></proto>
             <param group="ClipPlaneName"><ptype>GLenum</ptype> <name>plane</name></param>
             <param len="4">const <ptype>GLdouble</ptype> *<name>equation</name></param>
@@ -9761,6 +10361,15 @@
             <alias name="glColorMaski"/>
         </command>
         <command>
+            <proto>void <name>glColorMaskiOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>r</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>g</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>b</name></param>
+            <param group="Boolean"><ptype>GLboolean</ptype> <name>a</name></param>
+            <alias name="glColorMaski"/>
+        </command>
+        <command>
             <proto>void <name>glColorMaterial</name></proto>
             <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
             <param group="ColorMaterialParameter"><ptype>GLenum</ptype> <name>mode</name></param>
@@ -9953,6 +10562,15 @@
             <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glCommandListSegmentsNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+            <param><ptype>GLuint</ptype> <name>segments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCompileCommandListNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+        </command>
+        <command>
             <proto>void <name>glCompileShader</name></proto>
             <param><ptype>GLuint</ptype> <name>shader</name></param>
         </command>
@@ -10270,6 +10888,16 @@
             <param len="imageSize">const void *<name>bits</name></param>
         </command>
         <command>
+            <proto>void <name>glCompressedTextureSubImage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glCompressedTextureSubImage1DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10281,6 +10909,18 @@
             <param len="imageSize">const void *<name>bits</name></param>
         </command>
         <command>
+            <proto>void <name>glCompressedTextureSubImage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glCompressedTextureSubImage2DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10294,6 +10934,20 @@
             <param len="imageSize">const void *<name>bits</name></param>
         </command>
         <command>
+            <proto>void <name>glCompressedTextureSubImage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLsizei</ptype> <name>imageSize</name></param>
+            <param>const void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glCompressedTextureSubImage3DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10309,6 +10963,11 @@
             <param len="imageSize">const void *<name>bits</name></param>
         </command>
         <command>
+            <proto>void <name>glConservativeRasterParameterfNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glConvolutionFilter1D</name></proto>
             <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
@@ -10577,6 +11236,25 @@
             <glx type="render" opcode="4291"/>
         </command>
         <command>
+            <proto>void <name>glCopyImageSubDataOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>srcName</name></param>
+            <param><ptype>GLenum</ptype> <name>srcTarget</name></param>
+            <param><ptype>GLint</ptype> <name>srcLevel</name></param>
+            <param><ptype>GLint</ptype> <name>srcX</name></param>
+            <param><ptype>GLint</ptype> <name>srcY</name></param>
+            <param><ptype>GLint</ptype> <name>srcZ</name></param>
+            <param><ptype>GLuint</ptype> <name>dstName</name></param>
+            <param><ptype>GLenum</ptype> <name>dstTarget</name></param>
+            <param><ptype>GLint</ptype> <name>dstLevel</name></param>
+            <param><ptype>GLint</ptype> <name>dstX</name></param>
+            <param><ptype>GLint</ptype> <name>dstY</name></param>
+            <param><ptype>GLint</ptype> <name>dstZ</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcWidth</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcHeight</name></param>
+            <param><ptype>GLsizei</ptype> <name>srcDepth</name></param>
+            <alias name="glCopyImageSubData"/>
+        </command>
+        <command>
             <proto>void <name>glCopyMultiTexImage1DEXT</name></proto>
             <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10635,6 +11313,14 @@
             <param><ptype>GLsizei</ptype> <name>height</name></param>
         </command>
         <command>
+            <proto>void <name>glCopyNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>readBuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>writeBuffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>readOffset</name></param>
+            <param><ptype>GLintptr</ptype> <name>writeOffset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
             <proto>void <name>glCopyPathNV</name></proto>
             <param group="Path"><ptype>GLuint</ptype> <name>resultPath</name></param>
             <param group="Path"><ptype>GLuint</ptype> <name>srcPath</name></param>
@@ -10813,6 +11499,15 @@
             <param><ptype>GLsizei</ptype> <name>sourceLevelCount</name></param>
         </command>
         <command>
+            <proto>void <name>glCopyTextureSubImage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
             <proto>void <name>glCopyTextureSubImage1DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10823,6 +11518,17 @@
             <param><ptype>GLsizei</ptype> <name>width</name></param>
         </command>
         <command>
+            <proto>void <name>glCopyTextureSubImage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
             <proto>void <name>glCopyTextureSubImage2DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10835,6 +11541,18 @@
             <param><ptype>GLsizei</ptype> <name>height</name></param>
         </command>
         <command>
+            <proto>void <name>glCopyTextureSubImage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
             <proto>void <name>glCopyTextureSubImage3DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -10882,10 +11600,34 @@
             <param><ptype>GLboolean</ptype> <name>mask</name></param>
         </command>
         <command>
+            <proto>void <name>glCoverageModulationNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>components</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCoverageModulationTableNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto>void <name>glCoverageOperationNV</name></proto>
             <param><ptype>GLenum</ptype> <name>operation</name></param>
         </command>
         <command>
+            <proto>void <name>glCreateBuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>buffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateCommandListsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>lists</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateFramebuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>framebuffers</name></param>
+        </command>
+        <command>
             <proto>void <name>glCreatePerfQueryINTEL</name></proto>
             <param><ptype>GLuint</ptype> <name>queryId</name></param>
             <param><ptype>GLuint</ptype> *<name>queryHandle</name></param>
@@ -10898,6 +11640,27 @@
             <alias name="glCreateProgram"/>
         </command>
         <command>
+            <proto>void <name>glCreateProgramPipelines</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>pipelines</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateQueries</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateRenderbuffers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>renderbuffers</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateSamplers</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>samplers</name></param>
+        </command>
+        <command>
             <proto><ptype>GLuint</ptype> <name>glCreateShader</name></proto>
             <param><ptype>GLenum</ptype> <name>type</name></param>
         </command>
@@ -10924,12 +11687,33 @@
             <param len="count">const <ptype>GLchar</ptype> **<name>strings</name></param>
         </command>
         <command>
+            <proto>void <name>glCreateStatesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>states</name></param>
+        </command>
+        <command>
             <proto group="sync"><ptype>GLsync</ptype> <name>glCreateSyncFromCLeventARB</name></proto>
             <param group="cl_context"><ptype>struct _cl_context</ptype> *<name>context</name></param>
             <param group="cl_event"><ptype>struct _cl_event</ptype> *<name>event</name></param>
             <param><ptype>GLbitfield</ptype> <name>flags</name></param>
         </command>
         <command>
+            <proto>void <name>glCreateTextures</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>textures</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateTransformFeedbacks</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>ids</name></param>
+        </command>
+        <command>
+            <proto>void <name>glCreateVertexArrays</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param><ptype>GLuint</ptype> *<name>arrays</name></param>
+        </command>
+        <command>
             <proto>void <name>glCullFace</name></proto>
             <param group="CullFaceMode"><ptype>GLenum</ptype> <name>mode</name></param>
             <glx type="render" opcode="79"/>
@@ -11107,6 +11891,11 @@
             <alias name="glDeleteBuffers"/>
         </command>
         <command>
+            <proto>void <name>glDeleteCommandListsNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>lists</name></param>
+        </command>
+        <command>
             <proto>void <name>glDeleteFencesAPPLE</name></proto>
             <param><ptype>GLsizei</ptype> <name>n</name></param>
             <param group="FenceNV" len="n">const <ptype>GLuint</ptype> *<name>fences</name></param>
@@ -11253,6 +12042,11 @@
             <glx type="single" opcode="195"/>
         </command>
         <command>
+            <proto>void <name>glDeleteStatesNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+        </command>
+        <command>
             <proto>void <name>glDeleteSync</name></proto>
             <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
         </command>
@@ -11335,6 +12129,12 @@
             <glx type="render" opcode="174"/>
         </command>
         <command>
+            <proto>void <name>glDepthRangeArrayfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto>void <name>glDepthRangeArrayv</name></proto>
             <param><ptype>GLuint</ptype> <name>first</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -11347,6 +12147,12 @@
             <param><ptype>GLdouble</ptype> <name>f</name></param>
         </command>
         <command>
+            <proto>void <name>glDepthRangeIndexedfNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>n</name></param>
+            <param><ptype>GLfloat</ptype> <name>f</name></param>
+        </command>
+        <command>
             <proto>void <name>glDepthRangedNV</name></proto>
             <param><ptype>GLdouble</ptype> <name>zNear</name></param>
             <param><ptype>GLdouble</ptype> <name>zFar</name></param>
@@ -11426,6 +12232,11 @@
             <param><ptype>GLuint</ptype> <name>id</name></param>
         </command>
         <command>
+            <proto>void <name>glDisableVertexArrayAttrib</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
             <proto>void <name>glDisableVertexArrayAttribEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
@@ -11461,6 +12272,18 @@
             <alias name="glDisablei"/>
         </command>
         <command>
+            <proto>void <name>glDisableiNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisablei"/>
+        </command>
+        <command>
+            <proto>void <name>glDisableiOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glDisablei"/>
+        </command>
+        <command>
             <proto>void <name>glDiscardFramebufferEXT</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
@@ -11536,6 +12359,15 @@
             <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
             <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
         </command>
+        <command>
+            <proto>void <name>glDrawArraysInstancedBaseInstanceEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+            <alias name="glDrawArraysInstancedBaseInstance"/>
+        </command>
         <command comment="primcount should be renamed to instanceCount for OpenGL ES">
             <proto>void <name>glDrawArraysInstancedEXT</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
@@ -11554,7 +12386,7 @@
         </command>
         <command>
             <proto>void <name>glDrawBuffer</name></proto>
-            <param group="DrawBufferMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param group="DrawBufferMode"><ptype>GLenum</ptype> <name>buf</name></param>
             <glx type="render" opcode="126"/>
         </command>
         <command>
@@ -11594,6 +12426,38 @@
             <param len="n">const <ptype>GLenum</ptype> *<name>bufs</name></param>
         </command>
         <command>
+            <proto>void <name>glDrawCommandsAddressNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+            <param>const <ptype>GLuint64</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>primitiveMode</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param>const <ptype>GLintptr</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsStatesAddressNV</name></proto>
+            <param>const <ptype>GLuint64</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>fbos</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
+            <proto>void <name>glDrawCommandsStatesNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param>const <ptype>GLintptr</ptype> *<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>fbos</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
             <proto>void <name>glDrawElementArrayAPPLE</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param><ptype>GLint</ptype> <name>first</name></param>
@@ -11620,6 +12484,24 @@
             <param><ptype>GLint</ptype> <name>basevertex</name></param>
         </command>
         <command>
+            <proto>void <name>glDrawElementsBaseVertexEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsBaseVertexOES</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsBaseVertex"/>
+        </command>
+        <command>
             <proto>void <name>glDrawElementsIndirect</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param><ptype>GLenum</ptype> <name>type</name></param>
@@ -11661,6 +12543,16 @@
             <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
         </command>
         <command>
+            <proto>void <name>glDrawElementsInstancedBaseInstanceEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="count">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+            <alias name="glDrawElementsInstancedBaseInstance"/>
+        </command>
+        <command>
             <proto>void <name>glDrawElementsInstancedBaseVertex</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -11679,6 +12571,37 @@
             <param><ptype>GLint</ptype> <name>basevertex</name></param>
             <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
         </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexBaseInstanceEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="count">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <param><ptype>GLuint</ptype> <name>baseinstance</name></param>
+            <alias name="glDrawElementsInstancedBaseVertexBaseInstance"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsInstancedBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawElementsInstancedBaseVertexOES</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>instancecount</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawElementsInstancedBaseVertex"/>
+        </command>
         <command comment="primcount should be renamed to instanceCount for OpenGL ES">
             <proto>void <name>glDrawElementsInstancedEXT</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
@@ -11749,6 +12672,28 @@
             <param><ptype>GLint</ptype> <name>basevertex</name></param>
         </command>
         <command>
+            <proto>void <name>glDrawRangeElementsBaseVertexEXT</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawRangeElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glDrawRangeElementsBaseVertexOES</name></proto>
+            <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLuint</ptype> <name>end</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(count,type)">const void *<name>indices</name></param>
+            <param><ptype>GLint</ptype> <name>basevertex</name></param>
+            <alias name="glDrawRangeElementsBaseVertex"/>
+        </command>
+        <command>
             <proto>void <name>glDrawRangeElementsEXT</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param><ptype>GLuint</ptype> <name>start</name></param>
@@ -11935,6 +12880,11 @@
             <param><ptype>GLuint</ptype> <name>id</name></param>
         </command>
         <command>
+            <proto>void <name>glEnableVertexArrayAttrib</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+        </command>
+        <command>
             <proto>void <name>glEnableVertexArrayAttribEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
@@ -11970,6 +12920,18 @@
             <alias name="glEnablei"/>
         </command>
         <command>
+            <proto>void <name>glEnableiNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnablei"/>
+        </command>
+        <command>
+            <proto>void <name>glEnableiOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glEnablei"/>
+        </command>
+        <command>
             <proto>void <name>glEnd</name></proto>
             <glx type="render" opcode="23"/>
         </command>
@@ -12136,6 +13098,9 @@
             <glx type="render" opcode="158"/>
         </command>
         <command>
+            <proto>void <name>glEvaluateDepthValuesARB</name></proto>
+        </command>
+        <command>
             <proto>void <name>glExecuteProgramNV</name></proto>
             <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLuint</ptype> <name>id</name></param>
@@ -12310,6 +13275,12 @@
             <alias name="glFlushMappedBufferRange"/>
         </command>
         <command>
+            <proto>void <name>glFlushMappedNamedBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+        </command>
+        <command>
             <proto>void <name>glFlushMappedNamedBufferRangeEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLintptr</ptype> <name>offset</name></param>
@@ -12470,6 +13441,10 @@
             <param group="MaterialParameter"><ptype>GLenum</ptype> <name>mode</name></param>
         </command>
         <command>
+            <proto>void <name>glFragmentCoverageColorNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>color</name></param>
+        </command>
+        <command>
             <proto>void <name>glFragmentLightModelfSGIX</name></proto>
             <param group="FragmentLightModelParameterSGIX"><ptype>GLenum</ptype> <name>pname</name></param>
             <param group="CheckedFloat32"><ptype>GLfloat</ptype> <name>param</name></param>
@@ -12592,6 +13567,20 @@
             <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
         </command>
         <command>
+            <proto>void <name>glFramebufferSampleLocationsfvARB</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferSampleLocationsfvNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto>void <name>glFramebufferTexture</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>attachment</name></param>
@@ -12707,7 +13696,7 @@
             <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
-            <alias name="glFramebufferTextureARB"/>
+            <alias name="glFramebufferTexture"/>
         </command>
         <command>
             <proto>void <name>glFramebufferTextureFaceARB</name></proto>
@@ -12754,6 +13743,33 @@
             <alias name="glFramebufferTextureLayer"/>
         </command>
         <command>
+            <proto>void <name>glFramebufferTextureMultisampleMultiviewOVR</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLint</ptype> <name>baseViewIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numViews</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureMultiviewOVR</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>baseViewIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numViews</name></param>
+        </command>
+        <command>
+            <proto>void <name>glFramebufferTextureOES</name></proto>
+            <param group="FramebufferTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
+            <param group="CheckedInt32"><ptype>GLint</ptype> <name>level</name></param>
+            <alias name="glFramebufferTexture"/>
+        </command>
+        <command>
             <proto>void <name>glFreeObjectBufferATI</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
         </command>
@@ -13018,6 +14034,10 @@
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
         </command>
         <command>
+            <proto>void <name>glGenerateTextureMipmap</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+        </command>
+        <command>
             <proto>void <name>glGenerateTextureMipmapEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -13110,7 +14130,7 @@
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLuint</ptype> <name>uniformBlockIndex</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
-            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(program,uniformBlockIndex,pname)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glGetActiveUniformName</name></proto>
@@ -13124,9 +14144,9 @@
             <proto>void <name>glGetActiveUniformsiv</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLsizei</ptype> <name>uniformCount</name></param>
-            <param len="COMPSIZE(uniformCount)">const <ptype>GLuint</ptype> *<name>uniformIndices</name></param>
+            <param len="uniformCount">const <ptype>GLuint</ptype> *<name>uniformIndices</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
-            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(uniformCount,pname)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glGetActiveVaryingNV</name></proto>
@@ -13389,6 +14409,11 @@
             <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto><ptype>GLuint</ptype> <name>glGetCommandHeaderNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>tokenID</name></param>
+            <param><ptype>GLuint</ptype> <name>size</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetCompressedMultiTexImageEXT</name></proto>
             <param group="TextureUnit"><ptype>GLenum</ptype> <name>texunit</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -13412,6 +14437,13 @@
             <glx type="single" opcode="160"/>
         </command>
         <command>
+            <proto>void <name>glGetCompressedTextureImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetCompressedTextureImageEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -13419,6 +14451,19 @@
             <param len="COMPSIZE(target,lod)">void *<name>img</name></param>
         </command>
         <command>
+            <proto>void <name>glGetCompressedTextureSubImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetConvolutionFilter</name></proto>
             <param group="ConvolutionTarget"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
@@ -13470,6 +14515,11 @@
             <param len="COMPSIZE(pname)"><ptype>GLfixed</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetCoverageModulationTableNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto><ptype>GLuint</ptype> <name>glGetDebugMessageLog</name></proto>
             <param><ptype>GLuint</ptype> <name>count</name></param>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
@@ -13537,7 +14587,7 @@
             <proto>void <name>glGetDoublei_vEXT</name></proto>
             <param group="TypeEnum"><ptype>GLenum</ptype> <name>pname</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
-            <param len="COMPSIZE(target)"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLdouble</ptype> *<name>params</name></param>
             <alias name="glGetDoublei_v"/>
         </command>
         <command>
@@ -13615,7 +14665,14 @@
             <proto>void <name>glGetFloati_vEXT</name></proto>
             <param group="TypeEnum"><ptype>GLenum</ptype> <name>pname</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
-            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetFloati_v"/>
+        </command>
+        <command>
+            <proto>void <name>glGetFloati_vNV</name></proto>
+            <param group="TypeEnum"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="COMPSIZE(target)"><ptype>GLfloat</ptype> *<name>data</name></param>
             <alias name="glGetFloati_v"/>
         </command>
         <command>
@@ -13634,6 +14691,12 @@
             <param>const <ptype>GLchar</ptype> *<name>name</name></param>
         </command>
         <command>
+            <proto><ptype>GLint</ptype> <name>glGetFragDataIndexEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param>const <ptype>GLchar</ptype> *<name>name</name></param>
+            <alias name="glGetFragDataIndex"/>
+        </command>
+        <command>
             <proto><ptype>GLint</ptype> <name>glGetFragDataLocation</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
@@ -13705,12 +14768,19 @@
             <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatus</name></proto>
+        </command>
+        <command>
             <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatusARB</name></proto>
         </command>
         <command>
             <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatusEXT</name></proto>
         </command>
         <command>
+            <proto><ptype>GLenum</ptype> <name>glGetGraphicsResetStatusKHR</name></proto>
+            <alias name="glGetGraphicsResetStatus"/>
+        </command>
+        <command>
             <proto group="handleARB"><ptype>GLhandleARB</ptype> <name>glGetHandleARB</name></proto>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
         </command>
@@ -13860,6 +14930,15 @@
             <glx type="single" opcode="117"/>
         </command>
         <command>
+            <proto>void <name>glGetInternalformatSampleivNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetInternalformati64v</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>internalformat</name></param>
@@ -14199,6 +15278,18 @@
             <alias name="glGetMultisamplefv"/>
         </command>
         <command>
+            <proto>void <name>glGetNamedBufferParameteri64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetNamedBufferParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetNamedBufferParameterivEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param group="VertexBufferObjectParameter"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -14211,12 +15302,25 @@
             <param len="COMPSIZE(pname)"><ptype>GLuint64EXT</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetNamedBufferPointerv</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>void **<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetNamedBufferPointervEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param group="VertexBufferObjectParameter"><ptype>GLenum</ptype> <name>pname</name></param>
             <param len="1">void **<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param>void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetNamedBufferSubDataEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLintptr</ptype> <name>offset</name></param>
@@ -14224,6 +15328,13 @@
             <param len="COMPSIZE(size)">void *<name>data</name></param>
         </command>
         <command>
+            <proto>void <name>glGetNamedFramebufferAttachmentParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetNamedFramebufferAttachmentParameterivEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
@@ -14231,6 +15342,12 @@
             <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetNamedFramebufferParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetNamedFramebufferParameterivEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="GetFramebufferParameter"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -14279,6 +15396,12 @@
             <param len="1"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetNamedRenderbufferParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetNamedRenderbufferParameterivEXT</name></proto>
             <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
             <param group="RenderbufferParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -14799,6 +15922,12 @@
             <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
         </command>
         <command>
+            <proto><ptype>GLint</ptype> <name>glGetProgramResourceLocationIndexEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetProgramResourceName</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLenum</ptype> <name>programInterface</name></param>
@@ -14808,6 +15937,17 @@
             <param len="bufSize"><ptype>GLchar</ptype> *<name>name</name></param>
         </command>
         <command>
+            <proto>void <name>glGetProgramResourcefvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLenum</ptype> <name>programInterface</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLsizei</ptype> <name>propCount</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>props</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLsizei</ptype> *<name>length</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetProgramResourceiv</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLenum</ptype> <name>programInterface</name></param>
@@ -14865,6 +16005,34 @@
             <glx type="vendor" opcode="1298"/>
         </command>
         <command>
+            <proto>void <name>glGetQueryBufferObjecti64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjectiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjectui64v</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetQueryBufferObjectuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>id</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetQueryIndexediv</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
@@ -14995,6 +16163,13 @@
             <alias name="glGetSamplerParameterIiv"/>
         </command>
         <command>
+            <proto>void <name>glGetSamplerParameterIivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetSamplerParameterIiv"/>
+        </command>
+        <command>
             <proto>void <name>glGetSamplerParameterIuiv</name></proto>
             <param><ptype>GLuint</ptype> <name>sampler</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
@@ -15008,6 +16183,13 @@
             <alias name="glGetSamplerParameterIuiv"/>
         </command>
         <command>
+            <proto>void <name>glGetSamplerParameterIuivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetSamplerParameterIuiv"/>
+        </command>
+        <command>
             <proto>void <name>glGetSamplerParameterfv</name></proto>
             <param><ptype>GLuint</ptype> <name>sampler</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
@@ -15084,6 +16266,10 @@
             <glx type="vendor" opcode="4097"/>
         </command>
         <command>
+            <proto><ptype>GLushort</ptype> <name>glGetStageIndexNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>shadertype</name></param>
+        </command>
+        <command>
             <proto group="String">const <ptype>GLubyte</ptype> *<name>glGetString</name></proto>
             <param group="StringName"><ptype>GLenum</ptype> <name>name</name></param>
             <glx type="single" opcode="129"/>
@@ -15252,6 +16438,13 @@
             <alias name="glGetTexParameterIiv"/>
         </command>
         <command>
+            <proto>void <name>glGetTexParameterIivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetTexParameterIiv"/>
+        </command>
+        <command>
             <proto>void <name>glGetTexParameterIuiv</name></proto>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -15266,6 +16459,13 @@
             <alias name="glGetTexParameterIuiv"/>
         </command>
         <command>
+            <proto>void <name>glGetTexParameterIuivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="GetTextureParameter"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetTexParameterIuiv"/>
+        </command>
+        <command>
             <proto>void <name>glGetTexParameterPointervAPPLE</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
@@ -15306,6 +16506,15 @@
             <param><ptype>GLuint</ptype> <name>texture</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureImageEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15315,6 +16524,13 @@
             <param len="COMPSIZE(target,level,format,type)">void *<name>pixels</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureLevelParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureLevelParameterfvEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15323,6 +16539,13 @@
             <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureLevelParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureLevelParameterivEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15331,6 +16554,12 @@
             <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureParameterIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureParameterIivEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15338,6 +16567,12 @@
             <param len="COMPSIZE(pname)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureParameterIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureParameterIuivEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15345,6 +16580,12 @@
             <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureParameterfvEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15352,6 +16593,12 @@
             <param len="COMPSIZE(pname)"><ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTextureParameterivEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -15369,6 +16616,21 @@
             <param><ptype>GLuint</ptype> <name>sampler</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTextureSubImage</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTrackMatrixivNV</name></proto>
             <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLuint</ptype> <name>address</name></param>
@@ -15404,6 +16666,26 @@
             <param len="1"><ptype>GLint</ptype> *<name>location</name></param>
         </command>
         <command>
+            <proto>void <name>glGetTransformFeedbacki64_v</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint64</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbacki_v</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetTransformFeedbackiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetTranslatedShaderSourceANGLE</name></proto>
             <param><ptype>GLuint</ptype> <name>shader</name></param>
             <param><ptype>GLsizei</ptype> <name>bufsize</name></param>
@@ -15453,41 +16735,53 @@
             <proto>void <name>glGetUniformdv</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
-            <param len="COMPSIZE(location)"><ptype>GLdouble</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLdouble</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glGetUniformfv</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
-            <param len="COMPSIZE(location)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glGetUniformfvARB</name></proto>
             <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
-            <param len="COMPSIZE(location)"><ptype>GLfloat</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(programObj,location)"><ptype>GLfloat</ptype> *<name>params</name></param>
             <alias name="glGetUniformfv"/>
         </command>
         <command>
+            <proto>void <name>glGetUniformi64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetUniformi64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
-            <param len="COMPSIZE(location)"><ptype>GLint64EXT</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLint64EXT</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glGetUniformiv</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
-            <param len="COMPSIZE(location)"><ptype>GLint</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glGetUniformivARB</name></proto>
             <param group="handleARB"><ptype>GLhandleARB</ptype> <name>programObj</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
-            <param len="COMPSIZE(location)"><ptype>GLint</ptype> *<name>params</name></param>
+            <param len="COMPSIZE(programObj,location)"><ptype>GLint</ptype> *<name>params</name></param>
             <alias name="glGetUniformiv"/>
         </command>
         <command>
+            <proto>void <name>glGetUniformui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param len="COMPSIZE(program,location)"><ptype>GLuint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetUniformui64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -15548,6 +16842,20 @@
             <param len="COMPSIZE(name)">const <ptype>GLchar</ptype> *<name>name</name></param>
         </command>
         <command>
+            <proto>void <name>glGetVertexArrayIndexed64iv</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint64</ptype> *<name>param</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetVertexArrayIndexediv</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetVertexArrayIntegeri_vEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>index</name></param>
@@ -15574,6 +16882,12 @@
             <param len="1">void **<name>param</name></param>
         </command>
         <command>
+            <proto>void <name>glGetVertexArrayiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetVertexAttribArrayObjectfvATI</name></proto>
             <param><ptype>GLuint</ptype> <name>index</name></param>
             <param group="ArrayObjectPNameATI"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -15784,6 +17098,14 @@
             <param len="COMPSIZE(pname)"><ptype>GLuint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnColorTable</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>table</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnColorTableARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>format</name></param>
@@ -15792,6 +17114,13 @@
             <param len="bufSize">void *<name>table</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnCompressedTexImage</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>lod</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnCompressedTexImageARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLint</ptype> <name>lod</name></param>
@@ -15799,6 +17128,14 @@
             <param len="bufSize">void *<name>img</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnConvolutionFilter</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>image</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnConvolutionFilterARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>format</name></param>
@@ -15807,6 +17144,15 @@
             <param len="bufSize">void *<name>image</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnHistogram</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>values</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnHistogramARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
@@ -15816,6 +17162,13 @@
             <param len="bufSize">void *<name>values</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnMapdv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLdouble</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnMapdvARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>query</name></param>
@@ -15823,6 +17176,13 @@
             <param len="bufSize"><ptype>GLdouble</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnMapfv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnMapfvARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>query</name></param>
@@ -15830,6 +17190,13 @@
             <param len="bufSize"><ptype>GLfloat</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnMapiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>query</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint</ptype> *<name>v</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnMapivARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>query</name></param>
@@ -15837,6 +17204,15 @@
             <param len="bufSize"><ptype>GLint</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnMinmax</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLboolean</ptype> <name>reset</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>values</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnMinmaxARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>reset</name></param>
@@ -15846,29 +17222,63 @@
             <param len="bufSize">void *<name>values</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnPixelMapfv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>values</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnPixelMapfvARB</name></proto>
             <param><ptype>GLenum</ptype> <name>map</name></param>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
             <param len="bufSize"><ptype>GLfloat</ptype> *<name>values</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnPixelMapuiv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>values</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnPixelMapuivARB</name></proto>
             <param><ptype>GLenum</ptype> <name>map</name></param>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
             <param len="bufSize"><ptype>GLuint</ptype> *<name>values</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnPixelMapusv</name></proto>
+            <param><ptype>GLenum</ptype> <name>map</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLushort</ptype> *<name>values</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnPixelMapusvARB</name></proto>
             <param><ptype>GLenum</ptype> <name>map</name></param>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
             <param len="bufSize"><ptype>GLushort</ptype> *<name>values</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnPolygonStipple</name></proto>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLubyte</ptype> *<name>pattern</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnPolygonStippleARB</name></proto>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
             <param len="bufSize"><ptype>GLubyte</ptype> *<name>pattern</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnSeparableFilter</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>rowBufSize</name></param>
+            <param>void *<name>row</name></param>
+            <param><ptype>GLsizei</ptype> <name>columnBufSize</name></param>
+            <param>void *<name>column</name></param>
+            <param>void *<name>span</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnSeparableFilterARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>format</name></param>
@@ -15880,6 +17290,15 @@
             <param len="0">void *<name>span</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnTexImage</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnTexImageARB</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLint</ptype> <name>level</name></param>
@@ -15889,6 +17308,13 @@
             <param len="bufSize">void *<name>img</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnUniformdv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLdouble</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnUniformdvARB</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -15896,6 +17322,13 @@
             <param len="bufSize"><ptype>GLdouble</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnUniformfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnUniformfvARB</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -15910,6 +17343,28 @@
             <param len="bufSize"><ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnUniformfvKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLfloat</ptype> *<name>params</name></param>
+            <alias name="glGetnUniformfv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformi64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnUniformivARB</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -15924,6 +17379,28 @@
             <param len="bufSize"><ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnUniformivKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glGetnUniformiv"/>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint64</ptype> *<name>params</name></param>
+        </command>
+        <command>
+            <proto>void <name>glGetnUniformuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glGetnUniformuivARB</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -15931,6 +17408,14 @@
             <param len="bufSize"><ptype>GLuint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glGetnUniformuivKHR</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param><ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glGetnUniformuiv"/>
+        </command>
+        <command>
             <proto>void <name>glGlobalAlphaFactorbSUN</name></proto>
             <param><ptype>GLbyte</ptype> <name>factor</name></param>
         </command>
@@ -16175,6 +17660,22 @@
             <param len="numAttachments">const <ptype>GLenum</ptype> *<name>attachments</name></param>
         </command>
         <command>
+            <proto>void <name>glInvalidateNamedFramebufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>attachments</name></param>
+        </command>
+        <command>
+            <proto>void <name>glInvalidateNamedFramebufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>attachments</name></param>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
             <proto>void <name>glInvalidateSubFramebuffer</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLsizei</ptype> <name>numAttachments</name></param>
@@ -16218,6 +17719,10 @@
             <param><ptype>GLenum</ptype> <name>target</name></param>
         </command>
         <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsCommandListNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+        </command>
+        <command>
             <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnabled</name></proto>
             <param group="EnableCap"><ptype>GLenum</ptype> <name>cap</name></param>
             <glx type="single" opcode="140"/>
@@ -16240,6 +17745,18 @@
             <alias name="glIsEnabledi"/>
         </command>
         <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnablediNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glIsEnabledi"/>
+        </command>
+        <command>
+            <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsEnablediOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <alias name="glIsEnabledi"/>
+        </command>
+        <command>
             <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsFenceAPPLE</name></proto>
             <param group="FenceNV"><ptype>GLuint</ptype> <name>fence</name></param>
         </command>
@@ -16378,6 +17895,10 @@
             <glx type="single" opcode="196"/>
         </command>
         <command>
+            <proto><ptype>GLboolean</ptype> <name>glIsStateNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>state</name></param>
+        </command>
+        <command>
             <proto group="Boolean"><ptype>GLboolean</ptype> <name>glIsSync</name></proto>
             <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
         </command>
@@ -16580,6 +18101,16 @@
             <glx type="render" opcode="3"/>
         </command>
         <command>
+            <proto>void <name>glListDrawCommandsStatesClientNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>list</name></param>
+            <param><ptype>GLuint</ptype> <name>segment</name></param>
+            <param>const void **<name>indirects</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>sizes</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>states</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>fbos</name></param>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
             <proto>void <name>glListParameterfSGIX</name></proto>
             <param group="List"><ptype>GLuint</ptype> <name>list</name></param>
             <param group="ListParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -16898,11 +18429,23 @@
             <param><ptype>GLfixed</ptype> <name>v2</name></param>
         </command>
         <command>
+            <proto>void *<name>glMapNamedBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLenum</ptype> <name>access</name></param>
+        </command>
+        <command>
             <proto>void *<name>glMapNamedBufferEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param group="VertexBufferObjectAccess"><ptype>GLenum</ptype> <name>access</name></param>
         </command>
         <command>
+            <proto>void *<name>glMapNamedBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>length</name></param>
+            <param><ptype>GLbitfield</ptype> <name>access</name></param>
+        </command>
+        <command>
             <proto>void *<name>glMapNamedBufferRangeEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLintptr</ptype> <name>offset</name></param>
@@ -17076,10 +18619,25 @@
             <glx type="render" opcode="4327"/>
         </command>
         <command>
+            <proto>void <name>glMatrixLoad3x2fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixLoad3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
             <proto>void <name>glMatrixLoadIdentityEXT</name></proto>
             <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
         </command>
         <command>
+            <proto>void <name>glMatrixLoadTranspose3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
             <proto>void <name>glMatrixLoadTransposedEXT</name></proto>
             <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
             <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
@@ -17105,6 +18663,21 @@
             <glx type="render" opcode="179"/>
         </command>
         <command>
+            <proto>void <name>glMatrixMult3x2fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMult3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
+            <proto>void <name>glMatrixMultTranspose3x3fNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>matrixMode</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>m</name></param>
+        </command>
+        <command>
             <proto>void <name>glMatrixMultTransposedEXT</name></proto>
             <param group="MatrixMode"><ptype>GLenum</ptype> <name>mode</name></param>
             <param len="16">const <ptype>GLdouble</ptype> *<name>m</name></param>
@@ -17187,6 +18760,10 @@
             <param><ptype>GLfloat</ptype> <name>z</name></param>
         </command>
         <command>
+            <proto>void <name>glMaxShaderCompilerThreadsARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>count</name></param>
+        </command>
+        <command>
             <proto>void <name>glMemoryBarrier</name></proto>
             <param><ptype>GLbitfield</ptype> <name>barriers</name></param>
         </command>
@@ -17299,6 +18876,15 @@
             <alias name="glMultiDrawArraysIndirect"/>
         </command>
         <command>
+            <proto>void <name>glMultiDrawArraysIndirectBindlessCountNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxDrawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>vertexBufferCount</name></param>
+        </command>
+        <command>
             <proto>void <name>glMultiDrawArraysIndirectBindlessNV</name></proto>
             <param><ptype>GLenum</ptype> <name>mode</name></param>
             <param>const void *<name>indirect</name></param>
@@ -17315,6 +18901,14 @@
             <param><ptype>GLsizei</ptype> <name>stride</name></param>
         </command>
         <command>
+            <proto>void <name>glMultiDrawArraysIndirectEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount,stride)">const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <alias name="glMultiDrawArraysIndirect"/>
+        </command>
+        <command>
             <proto>void <name>glMultiDrawElementArrayAPPLE</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param len="primcount">const <ptype>GLint</ptype> *<name>first</name></param>
@@ -17339,6 +18933,26 @@
             <param len="COMPSIZE(drawcount)">const <ptype>GLint</ptype> *<name>basevertex</name></param>
         </command>
         <command>
+            <proto>void <name>glMultiDrawElementsBaseVertexEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLint</ptype> *<name>basevertex</name></param>
+            <alias name="glMultiDrawElementsBaseVertex"/>
+        </command>
+        <command>
+            <proto>void <name>glMultiDrawElementsBaseVertexOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
+            <param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount)">const void *const*<name>indices</name></param>
+            <param><ptype>GLsizei</ptype> <name>primcount</name></param>
+            <param len="COMPSIZE(drawcount)">const <ptype>GLint</ptype> *<name>basevertex</name></param>
+            <alias name="glMultiDrawElementsBaseVertex"/>
+        </command>
+        <command>
             <proto>void <name>glMultiDrawElementsEXT</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>count</name></param>
@@ -17365,6 +18979,16 @@
             <alias name="glMultiDrawElementsIndirect"/>
         </command>
         <command>
+            <proto>void <name>glMultiDrawElementsIndirectBindlessCountNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>maxDrawCount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <param><ptype>GLint</ptype> <name>vertexBufferCount</name></param>
+        </command>
+        <command>
             <proto>void <name>glMultiDrawElementsIndirectBindlessNV</name></proto>
             <param><ptype>GLenum</ptype> <name>mode</name></param>
             <param><ptype>GLenum</ptype> <name>type</name></param>
@@ -17383,6 +19007,15 @@
             <param><ptype>GLsizei</ptype> <name>stride</name></param>
         </command>
         <command>
+            <proto>void <name>glMultiDrawElementsIndirectEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param len="COMPSIZE(drawcount,stride)">const void *<name>indirect</name></param>
+            <param><ptype>GLsizei</ptype> <name>drawcount</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+            <alias name="glMultiDrawElementsIndirect"/>
+        </command>
+        <command>
             <proto>void <name>glMultiDrawRangeElementArrayAPPLE</name></proto>
             <param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
             <param><ptype>GLuint</ptype> <name>start</name></param>
@@ -18293,6 +19926,13 @@
             <param len="COMPSIZE(format,type,width,height,depth)">const void *<name>pixels</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedBufferData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param>const void *<name>data</name></param>
+            <param><ptype>GLenum</ptype> <name>usage</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedBufferDataEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
@@ -18300,18 +19940,48 @@
             <param group="VertexBufferObjectUsage"><ptype>GLenum</ptype> <name>usage</name></param>
         </command>
         <command>
-            <proto>void <name>glNamedBufferStorageEXT</name></proto>
+            <proto>void <name>glNamedBufferPageCommitmentARB</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
             <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferPageCommitmentEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferStorage</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
             <param len="size">const void *<name>data</name></param>
             <param><ptype>GLbitfield</ptype> <name>flags</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedBufferStorageEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="size">const void *<name>data</name></param>
+            <param><ptype>GLbitfield</ptype> <name>flags</name></param>
+            <alias name="glNamedBufferStorage"/>
+        </command>
+        <command>
+            <proto>void <name>glNamedBufferSubData</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param len="COMPSIZE(size)">const void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedBufferSubDataEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
             <param><ptype>GLintptr</ptype> <name>offset</name></param>
-            <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
             <param len="COMPSIZE(size)">const void *<name>data</name></param>
+            <alias name="glNamedBufferSubData"/>
         </command>
         <command>
             <proto>void <name>glNamedCopyBufferSubDataEXT</name></proto>
@@ -18322,12 +19992,41 @@
             <param><ptype>GLsizeiptr</ptype> <name>size</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedFramebufferDrawBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>buf</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferDrawBuffers</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>n</name></param>
+            <param>const <ptype>GLenum</ptype> *<name>bufs</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferParameteri</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedFramebufferParameteriEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="FramebufferParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
             <param><ptype>GLint</ptype> <name>param</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedFramebufferReadBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>src</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferRenderbuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLenum</ptype> <name>renderbuffertarget</name></param>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedFramebufferRenderbufferEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
@@ -18335,6 +20034,27 @@
             <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedFramebufferSampleLocationsfvARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferSampleLocationsfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLuint</ptype> <name>start</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>v</name></param>
+        </command>
+        <command>
+            <proto>void <name>glNamedFramebufferTexture</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedFramebufferTexture1DEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
@@ -18375,6 +20095,14 @@
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>face</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedFramebufferTextureLayer</name></proto>
+            <param><ptype>GLuint</ptype> <name>framebuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>attachment</name></param>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>layer</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedFramebufferTextureLayerEXT</name></proto>
             <param group="Framebuffer"><ptype>GLuint</ptype> <name>framebuffer</name></param>
             <param group="FramebufferAttachment"><ptype>GLenum</ptype> <name>attachment</name></param>
@@ -18487,6 +20215,13 @@
             <param len="len">const void *<name>string</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedRenderbufferStorage</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedRenderbufferStorageEXT</name></proto>
             <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
             <param group="PixelInternalFormat"><ptype>GLenum</ptype> <name>internalformat</name></param>
@@ -18494,6 +20229,14 @@
             <param><ptype>GLsizei</ptype> <name>height</name></param>
         </command>
         <command>
+            <proto>void <name>glNamedRenderbufferStorageMultisample</name></proto>
+            <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
             <proto>void <name>glNamedRenderbufferStorageMultisampleCoverageEXT</name></proto>
             <param group="Renderbuffer"><ptype>GLuint</ptype> <name>renderbuffer</name></param>
             <param><ptype>GLsizei</ptype> <name>coverageSamples</name></param>
@@ -18861,6 +20604,12 @@
             <alias name="glPatchParameteri"/>
         </command>
         <command>
+            <proto>void <name>glPatchParameteriOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>value</name></param>
+            <alias name="glPatchParameteri"/>
+        </command>
+        <command>
             <proto>void <name>glPathColorGenNV</name></proto>
             <param group="PathColor"><ptype>GLenum</ptype> <name>color</name></param>
             <param group="PathGenMode"><ptype>GLenum</ptype> <name>genMode</name></param>
@@ -18898,6 +20647,26 @@
             <param group="PathGenMode"><ptype>GLenum</ptype> <name>genMode</name></param>
         </command>
         <command>
+            <proto><ptype>GLenum</ptype> <name>glPathGlyphIndexArrayNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param>const void *<name>fontName</name></param>
+            <param><ptype>GLbitfield</ptype> <name>fontStyle</name></param>
+            <param><ptype>GLuint</ptype> <name>firstGlyphIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numGlyphs</name></param>
+            <param><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+        </command>
+        <command>
+            <proto><ptype>GLenum</ptype> <name>glPathGlyphIndexRangeNV</name></proto>
+            <param><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param>const void *<name>fontName</name></param>
+            <param><ptype>GLbitfield</ptype> <name>fontStyle</name></param>
+            <param><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+            <param><ptype>GLuint</ptype> <name>baseAndCount</name>[2]</param>
+        </command>
+        <command>
             <proto>void <name>glPathGlyphRangeNV</name></proto>
             <param group="Path"><ptype>GLuint</ptype> <name>firstPathName</name></param>
             <param group="PathFontTarget"><ptype>GLenum</ptype> <name>fontTarget</name></param>
@@ -18923,6 +20692,18 @@
             <param><ptype>GLfloat</ptype> <name>emScale</name></param>
         </command>
         <command>
+            <proto><ptype>GLenum</ptype> <name>glPathMemoryGlyphIndexArrayNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>firstPathName</name></param>
+            <param><ptype>GLenum</ptype> <name>fontTarget</name></param>
+            <param><ptype>GLsizeiptr</ptype> <name>fontSize</name></param>
+            <param>const void *<name>fontData</name></param>
+            <param><ptype>GLsizei</ptype> <name>faceIndex</name></param>
+            <param><ptype>GLuint</ptype> <name>firstGlyphIndex</name></param>
+            <param><ptype>GLsizei</ptype> <name>numGlyphs</name></param>
+            <param><ptype>GLuint</ptype> <name>pathParameterTemplate</name></param>
+            <param><ptype>GLfloat</ptype> <name>emScale</name></param>
+        </command>
+        <command>
             <proto>void <name>glPathParameterfNV</name></proto>
             <param group="Path"><ptype>GLuint</ptype> <name>path</name></param>
             <param group="PathParameter"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -19271,12 +21052,25 @@
             <glx type="render" opcode="101"/>
         </command>
         <command>
+            <proto>void <name>glPolygonModeNV</name></proto>
+            <param group="MaterialFace"><ptype>GLenum</ptype> <name>face</name></param>
+            <param group="PolygonMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <alias name="glPolygonMode"/>
+        </command>
+        <command>
             <proto>void <name>glPolygonOffset</name></proto>
             <param><ptype>GLfloat</ptype> <name>factor</name></param>
             <param><ptype>GLfloat</ptype> <name>units</name></param>
             <glx type="render" opcode="192"/>
         </command>
         <command>
+            <proto>void <name>glPolygonOffsetClampEXT</name></proto>
+            <param><ptype>GLfloat</ptype> <name>factor</name></param>
+            <param><ptype>GLfloat</ptype> <name>units</name></param>
+            <param><ptype>GLfloat</ptype> <name>clamp</name></param>
+            <glx type="render" opcode="4225"/>
+        </command>
+        <command>
             <proto>void <name>glPolygonOffsetEXT</name></proto>
             <param><ptype>GLfloat</ptype> <name>factor</name></param>
             <param><ptype>GLfloat</ptype> <name>bias</name></param>
@@ -19354,6 +21148,29 @@
             <param><ptype>GLuint</ptype> <name>key1</name></param>
         </command>
         <command>
+            <proto>void <name>glPrimitiveBoundingBox</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveBoundingBoxARB</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+            <alias name="glPrimitiveBoundingBox"/>
+        </command>
+        <command>
             <proto>void <name>glPrimitiveBoundingBoxEXT</name></proto>
             <param><ptype>GLfloat</ptype> <name>minX</name></param>
             <param><ptype>GLfloat</ptype> <name>minY</name></param>
@@ -19363,6 +21180,19 @@
             <param><ptype>GLfloat</ptype> <name>maxY</name></param>
             <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
             <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+            <alias name="glPrimitiveBoundingBox"/>
+        </command>
+        <command>
+            <proto>void <name>glPrimitiveBoundingBoxOES</name></proto>
+            <param><ptype>GLfloat</ptype> <name>minX</name></param>
+            <param><ptype>GLfloat</ptype> <name>minY</name></param>
+            <param><ptype>GLfloat</ptype> <name>minZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>minW</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxX</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxY</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxZ</name></param>
+            <param><ptype>GLfloat</ptype> <name>maxW</name></param>
+            <alias name="glPrimitiveBoundingBox"/>
         </command>
         <command>
             <proto>void <name>glPrimitiveRestartIndex</name></proto>
@@ -19716,6 +21546,14 @@
             <glx type="render" opcode="4186"/>
         </command>
         <command>
+            <proto>void <name>glProgramPathFragmentInputGenNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLenum</ptype> <name>genMode</name></param>
+            <param><ptype>GLint</ptype> <name>components</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>coeffs</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramStringARB</name></proto>
             <param group="ProgramTargetARB"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="ProgramFormatARB"><ptype>GLenum</ptype> <name>format</name></param>
@@ -19789,12 +21627,25 @@
             <param><ptype>GLint</ptype> <name>v0</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform1i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform1i64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLint64EXT</ptype> <name>x</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform1i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform1i64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -19830,12 +21681,25 @@
             <param><ptype>GLuint</ptype> <name>v0</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform1ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform1ui64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform1ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform1ui64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -19930,6 +21794,13 @@
             <param><ptype>GLint</ptype> <name>v1</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform2i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform2i64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -19937,6 +21808,13 @@
             <param><ptype>GLint64EXT</ptype> <name>y</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform2i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform2i64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -19974,6 +21852,13 @@
             <param><ptype>GLuint</ptype> <name>v1</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform2ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform2ui64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -19981,6 +21866,13 @@
             <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform2ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform2ui64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20081,6 +21973,14 @@
             <param><ptype>GLint</ptype> <name>v2</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform3i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform3i64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20089,6 +21989,13 @@
             <param><ptype>GLint64EXT</ptype> <name>z</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform3i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform3i64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20128,6 +22035,14 @@
             <param><ptype>GLuint</ptype> <name>v2</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform3ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform3ui64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20136,6 +22051,13 @@
             <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform3ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform3ui64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20242,6 +22164,15 @@
             <param><ptype>GLint</ptype> <name>v3</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform4i64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+            <param><ptype>GLint64</ptype> <name>w</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform4i64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20251,6 +22182,13 @@
             <param><ptype>GLint64EXT</ptype> <name>w</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform4i64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform4i64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20292,6 +22230,15 @@
             <param><ptype>GLuint</ptype> <name>v3</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform4ui64ARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+            <param><ptype>GLuint64</ptype> <name>w</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform4ui64NV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20301,6 +22248,13 @@
             <param><ptype>GLuint64EXT</ptype> <name>w</name></param>
         </command>
         <command>
+            <proto>void <name>glProgramUniform4ui64vARB</name></proto>
+            <param><ptype>GLuint</ptype> <name>program</name></param>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glProgramUniform4ui64vNV</name></proto>
             <param><ptype>GLuint</ptype> <name>program</name></param>
             <param><ptype>GLint</ptype> <name>location</name></param>
@@ -20922,8 +22876,13 @@
             <param len="4">const <ptype>GLfixed</ptype> *<name>coords</name></param>
         </command>
         <command>
+            <proto>void <name>glRasterSamplesEXT</name></proto>
+            <param><ptype>GLuint</ptype> <name>samples</name></param>
+            <param><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
             <proto>void <name>glReadBuffer</name></proto>
-            <param group="ReadBufferMode"><ptype>GLenum</ptype> <name>mode</name></param>
+            <param group="ReadBufferMode"><ptype>GLenum</ptype> <name>src</name></param>
             <glx type="render" opcode="171"/>
         </command>
         <command>
@@ -20953,6 +22912,17 @@
             <glx type="render" opcode="345" name="glReadPixelsPBO" comment="PBO protocol"/>
         </command>
         <command>
+            <proto>void <name>glReadnPixels</name></proto>
+            <param><ptype>GLint</ptype> <name>x</name></param>
+            <param><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param>void *<name>data</name></param>
+        </command>
+        <command>
             <proto>void <name>glReadnPixelsARB</name></proto>
             <param><ptype>GLint</ptype> <name>x</name></param>
             <param><ptype>GLint</ptype> <name>y</name></param>
@@ -20962,6 +22932,7 @@
             <param><ptype>GLenum</ptype> <name>type</name></param>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
             <param len="bufSize">void *<name>data</name></param>
+            <alias name="glReadnPixels"/>
         </command>
         <command>
             <proto>void <name>glReadnPixelsEXT</name></proto>
@@ -20973,6 +22944,19 @@
             <param><ptype>GLenum</ptype> <name>type</name></param>
             <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
             <param len="bufSize">void *<name>data</name></param>
+            <alias name="glReadnPixels"/>
+        </command>
+        <command>
+            <proto>void <name>glReadnPixelsKHR</name></proto>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>x</name></param>
+            <param group="WinCoord"><ptype>GLint</ptype> <name>y</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param group="PixelFormat"><ptype>GLenum</ptype> <name>format</name></param>
+            <param group="PixelType"><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLsizei</ptype> <name>bufSize</name></param>
+            <param len="bufSize">void *<name>data</name></param>
+            <alias name="glReadnPixels"/>
         </command>
         <command>
             <proto>void <name>glRectd</name></proto>
@@ -21342,6 +23326,9 @@
             <proto>void <name>glResizeBuffersMESA</name></proto>
         </command>
         <command>
+            <proto>void <name>glResolveDepthValuesNV</name></proto>
+        </command>
+        <command>
             <proto>void <name>glResolveMultisampleFramebufferAPPLE</name></proto>
         </command>
         <command>
@@ -21394,11 +23381,6 @@
             <alias name="glSampleCoverage"/>
         </command>
         <command>
-            <proto>void <name>glSampleCoverageOES</name></proto>
-            <param group="ClampedFixed"><ptype>GLfixed</ptype> <name>value</name></param>
-            <param group="Boolean"><ptype>GLboolean</ptype> <name>invert</name></param>
-        </command>
-        <command>
             <proto>void <name>glSampleCoveragex</name></proto>
             <param><ptype>GLclampx</ptype> <name>value</name></param>
             <param><ptype>GLboolean</ptype> <name>invert</name></param>
@@ -21460,6 +23442,13 @@
             <alias name="glSamplerParameterIiv"/>
         </command>
         <command>
+            <proto>void <name>glSamplerParameterIivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>param</name></param>
+            <alias name="glSamplerParameterIiv"/>
+        </command>
+        <command>
             <proto>void <name>glSamplerParameterIuiv</name></proto>
             <param><ptype>GLuint</ptype> <name>sampler</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
@@ -21473,6 +23462,13 @@
             <alias name="glSamplerParameterIuiv"/>
         </command>
         <command>
+            <proto>void <name>glSamplerParameterIuivOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>sampler</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>param</name></param>
+            <alias name="glSamplerParameterIuiv"/>
+        </command>
+        <command>
             <proto>void <name>glSamplerParameterf</name></proto>
             <param><ptype>GLuint</ptype> <name>sampler</name></param>
             <param><ptype>GLenum</ptype> <name>pname</name></param>
@@ -21537,6 +23533,13 @@
             <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glScissorArrayvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glScissorArrayv"/>
+        </command>
+        <command>
             <proto>void <name>glScissorIndexed</name></proto>
             <param><ptype>GLuint</ptype> <name>index</name></param>
             <param><ptype>GLint</ptype> <name>left</name></param>
@@ -21545,11 +23548,26 @@
             <param><ptype>GLsizei</ptype> <name>height</name></param>
         </command>
         <command>
+            <proto>void <name>glScissorIndexedNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLint</ptype> <name>left</name></param>
+            <param><ptype>GLint</ptype> <name>bottom</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <alias name="glScissorIndexed"/>
+        </command>
+        <command>
             <proto>void <name>glScissorIndexedv</name></proto>
             <param><ptype>GLuint</ptype> <name>index</name></param>
             <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glScissorIndexedvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLint</ptype> *<name>v</name></param>
+            <alias name="glScissorIndexedv"/>
+        </command>
+        <command>
             <proto>void <name>glSecondaryColor3b</name></proto>
             <param group="ColorB"><ptype>GLbyte</ptype> <name>red</name></param>
             <param group="ColorB"><ptype>GLbyte</ptype> <name>green</name></param>
@@ -21979,6 +23997,11 @@
             <param><ptype>GLbitfield</ptype> <name>preserveMask</name></param>
         </command>
         <command>
+            <proto>void <name>glStateCaptureNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>state</name></param>
+            <param><ptype>GLenum</ptype> <name>mode</name></param>
+        </command>
+        <command>
             <proto>void <name>glStencilClearTagEXT</name></proto>
             <param><ptype>GLsizei</ptype> <name>stencilTagBits</name></param>
             <param><ptype>GLuint</ptype> <name>stencilClearTag</name></param>
@@ -22077,6 +24100,44 @@
             <param group="MaskedStencilValue"><ptype>GLuint</ptype> <name>mask</name></param>
         </command>
         <command>
+            <proto>void <name>glStencilThenCoverFillPathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param>const void *<name>paths</name></param>
+            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            <param><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverFillPathNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLenum</ptype> <name>fillMode</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverStrokePathInstancedNV</name></proto>
+            <param><ptype>GLsizei</ptype> <name>numPaths</name></param>
+            <param><ptype>GLenum</ptype> <name>pathNameType</name></param>
+            <param>const void *<name>paths</name></param>
+            <param><ptype>GLuint</ptype> <name>pathBase</name></param>
+            <param><ptype>GLint</ptype> <name>reference</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+            <param><ptype>GLenum</ptype> <name>transformType</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>transformValues</name></param>
+        </command>
+        <command>
+            <proto>void <name>glStencilThenCoverStrokePathNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>path</name></param>
+            <param><ptype>GLint</ptype> <name>reference</name></param>
+            <param><ptype>GLuint</ptype> <name>mask</name></param>
+            <param><ptype>GLenum</ptype> <name>coverMode</name></param>
+        </command>
+        <command>
             <proto>void <name>glStopInstrumentsSGIX</name></proto>
             <param><ptype>GLint</ptype> <name>marker</name></param>
             <glx type="render" opcode="2070"/>
@@ -22087,6 +24148,11 @@
             <param len="len">const void *<name>string</name></param>
         </command>
         <command>
+            <proto>void <name>glSubpixelPrecisionBiasNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>xbits</name></param>
+            <param><ptype>GLuint</ptype> <name>ybits</name></param>
+        </command>
+        <command>
             <proto>void <name>glSwizzleEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>res</name></param>
             <param><ptype>GLuint</ptype> <name>in</name></param>
@@ -22211,6 +24277,13 @@
             <alias name="glTexBuffer"/>
         </command>
         <command>
+            <proto>void <name>glTexBufferOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <alias name="glTexBuffer"/>
+        </command>
+        <command>
             <proto>void <name>glTexBufferRange</name></proto>
             <param><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLenum</ptype> <name>internalformat</name></param>
@@ -22228,6 +24301,15 @@
             <alias name="glTexBufferRange"/>
         </command>
         <command>
+            <proto>void <name>glTexBufferRangeOES</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param group="BufferOffset"><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+            <alias name="glTexBufferRange"/>
+        </command>
+        <command>
             <proto>void <name>glTexBumpParameterfvATI</name></proto>
             <param group="TexBumpParameterATI"><ptype>GLenum</ptype> <name>pname</name></param>
             <param len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>param</name></param>
@@ -23020,7 +25102,20 @@
             <param><ptype>GLsizei</ptype> <name>width</name></param>
             <param><ptype>GLsizei</ptype> <name>height</name></param>
             <param><ptype>GLsizei</ptype> <name>depth</name></param>
-            <param><ptype>GLboolean</ptype> <name>resident</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTexPageCommitmentEXT</name></proto>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+            <alias name="glTexPageCommitmentARB"/>
         </command>
         <command>
             <proto>void <name>glTexParameterIiv</name></proto>
@@ -23037,6 +25132,13 @@
             <alias name="glTexParameterIiv"/>
         </command>
         <command>
+            <proto>void <name>glTexParameterIivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
+            <alias name="glTexParameterIiv"/>
+        </command>
+        <command>
             <proto>void <name>glTexParameterIuiv</name></proto>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -23051,6 +25153,13 @@
             <alias name="glTexParameterIuiv"/>
         </command>
         <command>
+            <proto>void <name>glTexParameterIuivOES</name></proto>
+            <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
+            <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
+            <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
+            <alias name="glTexParameterIuiv"/>
+        </command>
+        <command>
             <proto>void <name>glTexParameterf</name></proto>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
             <param group="TextureParameterName"><ptype>GLenum</ptype> <name>pname</name></param>
@@ -23315,10 +25424,19 @@
             <glx type="render" opcode="2058"/>
         </command>
         <command>
+            <proto>void <name>glTextureBarrier</name></proto>
+        </command>
+        <command>
             <proto>void <name>glTextureBarrierNV</name></proto>
             <glx type="render" opcode="4348"/>
         </command>
         <command>
+            <proto>void <name>glTextureBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureBufferEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23326,6 +25444,14 @@
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureBufferRangeEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23448,7 +25574,13 @@
             <param><ptype>GLsizei</ptype> <name>width</name></param>
             <param><ptype>GLsizei</ptype> <name>height</name></param>
             <param><ptype>GLsizei</ptype> <name>depth</name></param>
-            <param><ptype>GLboolean</ptype> <name>resident</name></param>
+            <param><ptype>GLboolean</ptype> <name>commit</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTextureParameterIiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
             <proto>void <name>glTextureParameterIivEXT</name></proto>
@@ -23458,6 +25590,12 @@
             <param group="CheckedInt32" len="COMPSIZE(pname)">const <ptype>GLint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureParameterIuiv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>params</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureParameterIuivEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23465,6 +25603,12 @@
             <param len="COMPSIZE(pname)">const <ptype>GLuint</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureParameterf</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLfloat</ptype> <name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureParameterfEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23473,6 +25617,12 @@
             <vecequiv name="glTextureParameterfvEXT"/>
         </command>
         <command>
+            <proto>void <name>glTextureParameterfv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLfloat</ptype> *<name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureParameterfvEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23480,6 +25630,12 @@
             <param group="CheckedFloat32" len="COMPSIZE(pname)">const <ptype>GLfloat</ptype> *<name>params</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureParameteri</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param><ptype>GLint</ptype> <name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureParameteriEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23488,6 +25644,12 @@
             <vecequiv name="glTextureParameterivEXT"/>
         </command>
         <command>
+            <proto>void <name>glTextureParameteriv</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>pname</name></param>
+            <param>const <ptype>GLint</ptype> *<name>param</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureParameterivEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23507,6 +25669,13 @@
             <param><ptype>GLuint</ptype> <name>renderbuffer</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureStorage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureStorage1DEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>texture</name></param>
             <param><ptype>GLenum</ptype> <name>target</name></param>
@@ -23515,6 +25684,14 @@
             <param><ptype>GLsizei</ptype> <name>width</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureStorage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureStorage2DEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>texture</name></param>
             <param><ptype>GLenum</ptype> <name>target</name></param>
@@ -23524,6 +25701,15 @@
             <param><ptype>GLsizei</ptype> <name>height</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureStorage2DMultisample</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureStorage2DMultisampleEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23534,6 +25720,15 @@
             <param group="Boolean"><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureStorage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>levels</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureStorage3DEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>texture</name></param>
             <param><ptype>GLenum</ptype> <name>target</name></param>
@@ -23544,6 +25739,16 @@
             <param><ptype>GLsizei</ptype> <name>depth</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureStorage3DMultisample</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLsizei</ptype> <name>samples</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLboolean</ptype> <name>fixedsamplelocations</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureStorage3DMultisampleEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>texture</name></param>
             <param><ptype>GLenum</ptype> <name>target</name></param>
@@ -23566,6 +25771,16 @@
             <param><ptype>GLbitfield</ptype> <name>flags</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureSubImage1D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureSubImage1DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23577,6 +25792,18 @@
             <param len="COMPSIZE(format,type,width)">const void *<name>pixels</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureSubImage2D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureSubImage2DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23590,6 +25817,20 @@
             <param len="COMPSIZE(format,type,width,height)">const void *<name>pixels</name></param>
         </command>
         <command>
+            <proto>void <name>glTextureSubImage3D</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLint</ptype> <name>level</name></param>
+            <param><ptype>GLint</ptype> <name>xoffset</name></param>
+            <param><ptype>GLint</ptype> <name>yoffset</name></param>
+            <param><ptype>GLint</ptype> <name>zoffset</name></param>
+            <param><ptype>GLsizei</ptype> <name>width</name></param>
+            <param><ptype>GLsizei</ptype> <name>height</name></param>
+            <param><ptype>GLsizei</ptype> <name>depth</name></param>
+            <param><ptype>GLenum</ptype> <name>format</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param>const void *<name>pixels</name></param>
+        </command>
+        <command>
             <proto>void <name>glTextureSubImage3DEXT</name></proto>
             <param group="Texture"><ptype>GLuint</ptype> <name>texture</name></param>
             <param group="TextureTarget"><ptype>GLenum</ptype> <name>target</name></param>
@@ -23628,6 +25869,18 @@
             <alias name="glTextureView"/>
         </command>
         <command>
+            <proto>void <name>glTextureViewOES</name></proto>
+            <param><ptype>GLuint</ptype> <name>texture</name></param>
+            <param><ptype>GLenum</ptype> <name>target</name></param>
+            <param><ptype>GLuint</ptype> <name>origtexture</name></param>
+            <param><ptype>GLenum</ptype> <name>internalformat</name></param>
+            <param><ptype>GLuint</ptype> <name>minlevel</name></param>
+            <param><ptype>GLuint</ptype> <name>numlevels</name></param>
+            <param><ptype>GLuint</ptype> <name>minlayer</name></param>
+            <param><ptype>GLuint</ptype> <name>numlayers</name></param>
+            <alias name="glTextureView"/>
+        </command>
+        <command>
             <proto>void <name>glTrackMatrixNV</name></proto>
             <param group="VertexAttribEnumNV"><ptype>GLenum</ptype> <name>target</name></param>
             <param><ptype>GLuint</ptype> <name>address</name></param>
@@ -23637,11 +25890,25 @@
         </command>
         <command>
             <proto>void <name>glTransformFeedbackAttribsNV</name></proto>
-            <param><ptype>GLuint</ptype> <name>count</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param len="COMPSIZE(count)">const <ptype>GLint</ptype> *<name>attribs</name></param>
             <param><ptype>GLenum</ptype> <name>bufferMode</name></param>
         </command>
         <command>
+            <proto>void <name>glTransformFeedbackBufferBase</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
+            <proto>void <name>glTransformFeedbackBufferRange</name></proto>
+            <param><ptype>GLuint</ptype> <name>xfb</name></param>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param group="BufferSize"><ptype>GLsizeiptr</ptype> <name>size</name></param>
+        </command>
+        <command>
             <proto>void <name>glTransformFeedbackStreamAttribsNV</name></proto>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param len="count">const <ptype>GLint</ptype> *<name>attribs</name></param>
@@ -23713,7 +25980,7 @@
             <proto>void <name>glUniform1dv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform1f</name></proto>
@@ -23730,13 +25997,13 @@
             <proto>void <name>glUniform1fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform1fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniform1fv"/>
         </command>
         <command>
@@ -23745,15 +26012,26 @@
             <param><ptype>GLint</ptype> <name>v0</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform1i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform1i64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLint64EXT</ptype> <name>x</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform1i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform1i64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLint64EXT</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform1iARB</name></proto>
@@ -23765,13 +26043,13 @@
             <proto>void <name>glUniform1iv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLint</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform1ivARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLint</ptype> *<name>value</name></param>
             <alias name="glUniform1iv"/>
         </command>
         <command>
@@ -23780,15 +26058,26 @@
             <param><ptype>GLuint</ptype> <name>v0</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform1ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform1ui64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform1ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*1">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform1ui64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform1uiEXT</name></proto>
@@ -23800,13 +26089,13 @@
             <proto>void <name>glUniform1uiv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLuint</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform1uivEXT</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLuint</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLuint</ptype> *<name>value</name></param>
             <alias name="glUniform1uiv"/>
         </command>
         <command>
@@ -23819,7 +26108,7 @@
             <proto>void <name>glUniform2dv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*2">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform2f</name></proto>
@@ -23838,13 +26127,13 @@
             <proto>void <name>glUniform2fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform2fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*2">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniform2fv"/>
         </command>
         <command>
@@ -23854,12 +26143,24 @@
             <param><ptype>GLint</ptype> <name>v1</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform2i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform2i64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLint64EXT</ptype> <name>x</name></param>
             <param><ptype>GLint64EXT</ptype> <name>y</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform2i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform2i64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -23876,13 +26177,13 @@
             <proto>void <name>glUniform2iv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*2">const <ptype>GLint</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform2ivARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*2">const <ptype>GLint</ptype> *<name>value</name></param>
             <alias name="glUniform2iv"/>
         </command>
         <command>
@@ -23892,12 +26193,24 @@
             <param><ptype>GLuint</ptype> <name>v1</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform2ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform2ui64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
             <param><ptype>GLuint64EXT</ptype> <name>y</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform2ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*2">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform2ui64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -23934,7 +26247,7 @@
             <proto>void <name>glUniform3dv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*3">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform3f</name></proto>
@@ -23955,13 +26268,13 @@
             <proto>void <name>glUniform3fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform3fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*3">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniform3fv"/>
         </command>
         <command>
@@ -23972,6 +26285,13 @@
             <param><ptype>GLint</ptype> <name>v2</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform3i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform3i64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLint64EXT</ptype> <name>x</name></param>
@@ -23979,6 +26299,12 @@
             <param><ptype>GLint64EXT</ptype> <name>z</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform3i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform3i64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -23996,13 +26322,13 @@
             <proto>void <name>glUniform3iv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*3">const <ptype>GLint</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform3ivARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*3">const <ptype>GLint</ptype> *<name>value</name></param>
             <alias name="glUniform3iv"/>
         </command>
         <command>
@@ -24013,6 +26339,13 @@
             <param><ptype>GLuint</ptype> <name>v2</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform3ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform3ui64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
@@ -24020,6 +26353,12 @@
             <param><ptype>GLuint64EXT</ptype> <name>z</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform3ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*3">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform3ui64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -24058,7 +26397,7 @@
             <proto>void <name>glUniform4dv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform4f</name></proto>
@@ -24081,13 +26420,13 @@
             <proto>void <name>glUniform4fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform4fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniform4fv"/>
         </command>
         <command>
@@ -24099,6 +26438,14 @@
             <param><ptype>GLint</ptype> <name>v3</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform4i64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLint64</ptype> <name>x</name></param>
+            <param><ptype>GLint64</ptype> <name>y</name></param>
+            <param><ptype>GLint64</ptype> <name>z</name></param>
+            <param><ptype>GLint64</ptype> <name>w</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform4i64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLint64EXT</ptype> <name>x</name></param>
@@ -24107,6 +26454,12 @@
             <param><ptype>GLint64EXT</ptype> <name>w</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform4i64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform4i64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -24125,13 +26478,13 @@
             <proto>void <name>glUniform4iv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniform4ivARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLint</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLint</ptype> *<name>value</name></param>
             <alias name="glUniform4iv"/>
         </command>
         <command>
@@ -24143,6 +26496,14 @@
             <param><ptype>GLuint</ptype> <name>v3</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform4ui64ARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLuint64</ptype> <name>x</name></param>
+            <param><ptype>GLuint64</ptype> <name>y</name></param>
+            <param><ptype>GLuint64</ptype> <name>z</name></param>
+            <param><ptype>GLuint64</ptype> <name>w</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform4ui64NV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLuint64EXT</ptype> <name>x</name></param>
@@ -24151,6 +26512,12 @@
             <param><ptype>GLuint64EXT</ptype> <name>w</name></param>
         </command>
         <command>
+            <proto>void <name>glUniform4ui64vARB</name></proto>
+            <param><ptype>GLint</ptype> <name>location</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="count*4">const <ptype>GLuint64</ptype> *<name>value</name></param>
+        </command>
+        <command>
             <proto>void <name>glUniform4ui64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
@@ -24217,21 +26584,21 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix2fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix2fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*4">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix2fv"/>
         </command>
         <command>
@@ -24239,14 +26606,14 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix2x3fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <glx type="render" opcode="305"/>
         </command>
         <command>
@@ -24254,7 +26621,7 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix2x3fv"/>
         </command>
         <command>
@@ -24262,14 +26629,14 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix2x4fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <glx type="render" opcode="307"/>
         </command>
         <command>
@@ -24277,7 +26644,7 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix2x4fv"/>
         </command>
         <command>
@@ -24285,21 +26652,21 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*9">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix3fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*9">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix3fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*9">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix3fv"/>
         </command>
         <command>
@@ -24307,14 +26674,14 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*6">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix3x2fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <glx type="render" opcode="306"/>
         </command>
         <command>
@@ -24322,7 +26689,7 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="6">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*6">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix3x2fv"/>
         </command>
         <command>
@@ -24330,14 +26697,14 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix3x4fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <glx type="render" opcode="309"/>
         </command>
         <command>
@@ -24345,7 +26712,7 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix3x4fv"/>
         </command>
         <command>
@@ -24353,21 +26720,21 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*16">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix4fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*16">const <ptype>GLfloat</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix4fvARB</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*16">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix4fv"/>
         </command>
         <command>
@@ -24375,14 +26742,14 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*8">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix4x2fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <glx type="render" opcode="308"/>
         </command>
         <command>
@@ -24390,7 +26757,7 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="8">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*8">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix4x2fv"/>
         </command>
         <command>
@@ -24398,14 +26765,14 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="count">const <ptype>GLdouble</ptype> *<name>value</name></param>
+            <param len="count*12">const <ptype>GLdouble</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUniformMatrix4x3fv</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <glx type="render" opcode="310"/>
         </command>
         <command>
@@ -24413,7 +26780,7 @@
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
             <param group="Boolean"><ptype>GLboolean</ptype> <name>transpose</name></param>
-            <param len="12">const <ptype>GLfloat</ptype> *<name>value</name></param>
+            <param len="count*12">const <ptype>GLfloat</ptype> *<name>value</name></param>
             <alias name="glUniformMatrix4x3fv"/>
         </command>
         <command>
@@ -24431,7 +26798,7 @@
             <proto>void <name>glUniformui64vNV</name></proto>
             <param><ptype>GLint</ptype> <name>location</name></param>
             <param><ptype>GLsizei</ptype> <name>count</name></param>
-            <param len="count">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
+            <param len="count*1">const <ptype>GLuint64EXT</ptype> *<name>value</name></param>
         </command>
         <command>
             <proto>void <name>glUnlockArraysEXT</name></proto>
@@ -24451,6 +26818,10 @@
             <alias name="glUnmapBuffer"/>
         </command>
         <command>
+            <proto><ptype>GLboolean</ptype> <name>glUnmapNamedBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
             <proto group="Boolean"><ptype>GLboolean</ptype> <name>glUnmapNamedBufferEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
         </command>
@@ -24625,6 +26996,7 @@
         <command>
             <proto>void <name>glVertex2bOES</name></proto>
             <param><ptype>GLbyte</ptype> <name>x</name></param>
+            <param><ptype>GLbyte</ptype> <name>y</name></param>
         </command>
         <command>
             <proto>void <name>glVertex2bvOES</name></proto>
@@ -24697,6 +27069,7 @@
             <proto>void <name>glVertex3bOES</name></proto>
             <param><ptype>GLbyte</ptype> <name>x</name></param>
             <param><ptype>GLbyte</ptype> <name>y</name></param>
+            <param><ptype>GLbyte</ptype> <name>z</name></param>
         </command>
         <command>
             <proto>void <name>glVertex3bvOES</name></proto>
@@ -24776,6 +27149,7 @@
             <param><ptype>GLbyte</ptype> <name>x</name></param>
             <param><ptype>GLbyte</ptype> <name>y</name></param>
             <param><ptype>GLbyte</ptype> <name>z</name></param>
+            <param><ptype>GLbyte</ptype> <name>w</name></param>
         </command>
         <command>
             <proto>void <name>glVertex4bvOES</name></proto>
@@ -24857,6 +27231,37 @@
             <param len="4">const <ptype>GLfixed</ptype> *<name>coords</name></param>
         </command>
         <command>
+            <proto>void <name>glVertexArrayAttribBinding</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLboolean</ptype> <name>normalized</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribIFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayAttribLFormat</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>attribindex</name></param>
+            <param><ptype>GLint</ptype> <name>size</name></param>
+            <param><ptype>GLenum</ptype> <name>type</name></param>
+            <param><ptype>GLuint</ptype> <name>relativeoffset</name></param>
+        </command>
+        <command>
             <proto>void <name>glVertexArrayBindVertexBufferEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
@@ -24865,6 +27270,12 @@
             <param><ptype>GLsizei</ptype> <name>stride</name></param>
         </command>
         <command>
+            <proto>void <name>glVertexArrayBindingDivisor</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>divisor</name></param>
+        </command>
+        <command>
             <proto>void <name>glVertexArrayColorOffsetEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
@@ -24881,6 +27292,11 @@
             <param><ptype>GLintptr</ptype> <name>offset</name></param>
         </command>
         <command>
+            <proto>void <name>glVertexArrayElementBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+        </command>
+        <command>
             <proto>void <name>glVertexArrayFogCoordOffsetEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
@@ -25022,6 +27438,23 @@
             <param><ptype>GLuint</ptype> <name>divisor</name></param>
         </command>
         <command>
+            <proto>void <name>glVertexArrayVertexBuffer</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>bindingindex</name></param>
+            <param><ptype>GLuint</ptype> <name>buffer</name></param>
+            <param><ptype>GLintptr</ptype> <name>offset</name></param>
+            <param><ptype>GLsizei</ptype> <name>stride</name></param>
+        </command>
+        <command>
+            <proto>void <name>glVertexArrayVertexBuffers</name></proto>
+            <param><ptype>GLuint</ptype> <name>vaobj</name></param>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param>const <ptype>GLuint</ptype> *<name>buffers</name></param>
+            <param>const <ptype>GLintptr</ptype> *<name>offsets</name></param>
+            <param>const <ptype>GLsizei</ptype> *<name>strides</name></param>
+        </command>
+        <command>
             <proto>void <name>glVertexArrayVertexOffsetEXT</name></proto>
             <param><ptype>GLuint</ptype> <name>vaobj</name></param>
             <param><ptype>GLuint</ptype> <name>buffer</name></param>
@@ -26905,6 +29338,13 @@
             <param len="COMPSIZE(count)">const <ptype>GLfloat</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glViewportArrayvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>first</name></param>
+            <param><ptype>GLsizei</ptype> <name>count</name></param>
+            <param len="COMPSIZE(count)">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glViewportArrayv"/>
+        </command>
+        <command>
             <proto>void <name>glViewportIndexedf</name></proto>
             <param><ptype>GLuint</ptype> <name>index</name></param>
             <param><ptype>GLfloat</ptype> <name>x</name></param>
@@ -26913,11 +29353,26 @@
             <param><ptype>GLfloat</ptype> <name>h</name></param>
         </command>
         <command>
+            <proto>void <name>glViewportIndexedfNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param><ptype>GLfloat</ptype> <name>x</name></param>
+            <param><ptype>GLfloat</ptype> <name>y</name></param>
+            <param><ptype>GLfloat</ptype> <name>w</name></param>
+            <param><ptype>GLfloat</ptype> <name>h</name></param>
+            <alias name="glViewportIndexedf"/>
+        </command>
+        <command>
             <proto>void <name>glViewportIndexedfv</name></proto>
             <param><ptype>GLuint</ptype> <name>index</name></param>
             <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
         </command>
         <command>
+            <proto>void <name>glViewportIndexedfvNV</name></proto>
+            <param><ptype>GLuint</ptype> <name>index</name></param>
+            <param len="4">const <ptype>GLfloat</ptype> *<name>v</name></param>
+            <alias name="glViewportIndexedfv"/>
+        </command>
+        <command>
             <proto>void <name>glWaitSync</name></proto>
             <param group="sync"><ptype>GLsync</ptype> <name>sync</name></param>
             <param><ptype>GLbitfield</ptype> <name>flags</name></param>
@@ -27356,6 +29811,7 @@
             <param group="VertexShaderWriteMaskEXT"><ptype>GLenum</ptype> <name>outZ</name></param>
             <param group="VertexShaderWriteMaskEXT"><ptype>GLenum</ptype> <name>outW</name></param>
         </command>
+
     </commands>
 
     <!-- SECTION: GL API interface definitions. -->
@@ -29043,6 +31499,22 @@
             <enum name="GL_COLOR_ATTACHMENT13"/>
             <enum name="GL_COLOR_ATTACHMENT14"/>
             <enum name="GL_COLOR_ATTACHMENT15"/>
+            <enum name="GL_COLOR_ATTACHMENT16"/>
+            <enum name="GL_COLOR_ATTACHMENT17"/>
+            <enum name="GL_COLOR_ATTACHMENT18"/>
+            <enum name="GL_COLOR_ATTACHMENT19"/>
+            <enum name="GL_COLOR_ATTACHMENT20"/>
+            <enum name="GL_COLOR_ATTACHMENT21"/>
+            <enum name="GL_COLOR_ATTACHMENT22"/>
+            <enum name="GL_COLOR_ATTACHMENT23"/>
+            <enum name="GL_COLOR_ATTACHMENT24"/>
+            <enum name="GL_COLOR_ATTACHMENT25"/>
+            <enum name="GL_COLOR_ATTACHMENT26"/>
+            <enum name="GL_COLOR_ATTACHMENT27"/>
+            <enum name="GL_COLOR_ATTACHMENT28"/>
+            <enum name="GL_COLOR_ATTACHMENT29"/>
+            <enum name="GL_COLOR_ATTACHMENT30"/>
+            <enum name="GL_COLOR_ATTACHMENT31"/>
             <enum name="GL_DEPTH_ATTACHMENT"/>
             <enum name="GL_STENCIL_ATTACHMENT"/>
             <enum name="GL_FRAMEBUFFER"/>
@@ -29190,11 +31662,13 @@
             <enum name="GL_UNIFORM_BUFFER_START"/>
             <enum name="GL_UNIFORM_BUFFER_SIZE"/>
             <enum name="GL_MAX_VERTEX_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
             <enum name="GL_MAX_FRAGMENT_UNIFORM_BLOCKS"/>
             <enum name="GL_MAX_COMBINED_UNIFORM_BLOCKS"/>
             <enum name="GL_MAX_UNIFORM_BUFFER_BINDINGS"/>
             <enum name="GL_MAX_UNIFORM_BLOCK_SIZE"/>
             <enum name="GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
             <enum name="GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS"/>
             <enum name="GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT"/>
             <enum name="GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH"/>
@@ -29213,6 +31687,7 @@
             <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS"/>
             <enum name="GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES"/>
             <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER"/>
+            <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER"/>
             <enum name="GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER"/>
             <enum name="GL_INVALID_INDEX"/>
             <command name="glGetUniformIndices"/>
@@ -29222,6 +31697,9 @@
             <command name="glGetActiveUniformBlockiv"/>
             <command name="glGetActiveUniformBlockName"/>
             <command name="glUniformBlockBinding"/>
+            <command name="glBindBufferRange"/>
+            <command name="glBindBufferBase"/>
+            <command name="glGetIntegeri_v"/>
         </require>
     </feature>
     <feature api="gl" name="GL_VERSION_3_2" number="3.2">
@@ -30538,6 +33016,12 @@
         </require>
     </feature>
     <feature api="gl" name="GL_VERSION_4_2" number="4.2">
+        <require comment="New aliases for old tokens">
+            <enum name="GL_COPY_READ_BUFFER_BINDING"/>
+            <enum name="GL_COPY_WRITE_BUFFER_BINDING"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_ACTIVE"/>
+            <enum name="GL_TRANSFORM_FEEDBACK_PAUSED"/>
+        </require>
         <require comment="Reuse tokens from ARB_base_instance (none)">
         </require>
         <require comment="Reuse tokens from ARB_shading_language_420pack (none)">
@@ -30758,6 +33242,7 @@
             <enum name="GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER"/>
             <enum name="GL_DISPATCH_INDIRECT_BUFFER"/>
             <enum name="GL_DISPATCH_INDIRECT_BUFFER_BINDING"/>
+            <enum name="GL_COMPUTE_SHADER_BIT"/>
         </require>
         <require comment="Reuse tokens from ARB_copy_image (none)">
         </require>
@@ -31175,6 +33660,191 @@
             <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV"/>
         </require>
     </feature>
+    <feature api="gl" name="GL_VERSION_4_5" number="4.5">
+        <require comment="Added robustness functionality">
+            <enum name="GL_CONTEXT_LOST"/>
+        </require>
+        <require comment="Reuse GL_ARB_clip_control">
+            <command name="glClipControl"/>
+            <enum name="GL_LOWER_LEFT"/>
+            <enum name="GL_UPPER_LEFT"/>
+            <enum name="GL_NEGATIVE_ONE_TO_ONE"/>
+            <enum name="GL_ZERO_TO_ONE"/>
+            <enum name="GL_CLIP_ORIGIN"/>
+            <enum name="GL_CLIP_DEPTH_MODE"/>
+        </require>
+        <require comment="Reuse GL_ARB_conditional_render_inverted">
+            <enum name="GL_QUERY_WAIT_INVERTED"/>
+            <enum name="GL_QUERY_NO_WAIT_INVERTED"/>
+            <enum name="GL_QUERY_BY_REGION_WAIT_INVERTED"/>
+            <enum name="GL_QUERY_BY_REGION_NO_WAIT_INVERTED"/>
+        </require>
+        <require comment="Reuse GL_ARB_cull_distance">
+            <enum name="GL_MAX_CULL_DISTANCES"/>
+            <enum name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+        </require>
+        <require comment="Reuse GL_ARB_direct_state_access">
+            <enum name="GL_TEXTURE_TARGET"/>
+            <enum name="GL_QUERY_TARGET"/>
+            <enum name="GL_TEXTURE_BINDING_1D"/>
+            <enum name="GL_TEXTURE_BINDING_1D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D"/>
+            <enum name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_3D"/>
+            <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_RECTANGLE"/>
+            <command name="glCreateTransformFeedbacks"/>
+            <command name="glTransformFeedbackBufferBase"/>
+            <command name="glTransformFeedbackBufferRange"/>
+            <command name="glGetTransformFeedbackiv"/>
+            <command name="glGetTransformFeedbacki_v"/>
+            <command name="glGetTransformFeedbacki64_v"/>
+            <command name="glCreateBuffers"/>
+            <command name="glNamedBufferStorage"/>
+            <command name="glNamedBufferData"/>
+            <command name="glNamedBufferSubData"/>
+            <command name="glCopyNamedBufferSubData"/>
+            <command name="glClearNamedBufferData"/>
+            <command name="glClearNamedBufferSubData"/>
+            <command name="glMapNamedBuffer"/>
+            <command name="glMapNamedBufferRange"/>
+            <command name="glUnmapNamedBuffer"/>
+            <command name="glFlushMappedNamedBufferRange"/>
+            <command name="glGetNamedBufferParameteriv"/>
+            <command name="glGetNamedBufferParameteri64v"/>
+            <command name="glGetNamedBufferPointerv"/>
+            <command name="glGetNamedBufferSubData"/>
+            <command name="glCreateFramebuffers"/>
+            <command name="glNamedFramebufferRenderbuffer"/>
+            <command name="glNamedFramebufferParameteri"/>
+            <command name="glNamedFramebufferTexture"/>
+            <command name="glNamedFramebufferTextureLayer"/>
+            <command name="glNamedFramebufferDrawBuffer"/>
+            <command name="glNamedFramebufferDrawBuffers"/>
+            <command name="glNamedFramebufferReadBuffer"/>
+            <command name="glInvalidateNamedFramebufferData"/>
+            <command name="glInvalidateNamedFramebufferSubData"/>
+            <command name="glClearNamedFramebufferiv"/>
+            <command name="glClearNamedFramebufferuiv"/>
+            <command name="glClearNamedFramebufferfv"/>
+            <command name="glClearNamedFramebufferfi"/>
+            <command name="glBlitNamedFramebuffer"/>
+            <command name="glCheckNamedFramebufferStatus"/>
+            <command name="glGetNamedFramebufferParameteriv"/>
+            <command name="glGetNamedFramebufferAttachmentParameteriv"/>
+            <command name="glCreateRenderbuffers"/>
+            <command name="glNamedRenderbufferStorage"/>
+            <command name="glNamedRenderbufferStorageMultisample"/>
+            <command name="glGetNamedRenderbufferParameteriv"/>
+            <command name="glCreateTextures"/>
+            <command name="glTextureBuffer"/>
+            <command name="glTextureBufferRange"/>
+            <command name="glTextureStorage1D"/>
+            <command name="glTextureStorage2D"/>
+            <command name="glTextureStorage3D"/>
+            <command name="glTextureStorage2DMultisample"/>
+            <command name="glTextureStorage3DMultisample"/>
+            <command name="glTextureSubImage1D"/>
+            <command name="glTextureSubImage2D"/>
+            <command name="glTextureSubImage3D"/>
+            <command name="glCompressedTextureSubImage1D"/>
+            <command name="glCompressedTextureSubImage2D"/>
+            <command name="glCompressedTextureSubImage3D"/>
+            <command name="glCopyTextureSubImage1D"/>
+            <command name="glCopyTextureSubImage2D"/>
+            <command name="glCopyTextureSubImage3D"/>
+            <command name="glTextureParameterf"/>
+            <command name="glTextureParameterfv"/>
+            <command name="glTextureParameteri"/>
+            <command name="glTextureParameterIiv"/>
+            <command name="glTextureParameterIuiv"/>
+            <command name="glTextureParameteriv"/>
+            <command name="glGenerateTextureMipmap"/>
+            <command name="glBindTextureUnit"/>
+            <command name="glGetTextureImage"/>
+            <command name="glGetCompressedTextureImage"/>
+            <command name="glGetTextureLevelParameterfv"/>
+            <command name="glGetTextureLevelParameteriv"/>
+            <command name="glGetTextureParameterfv"/>
+            <command name="glGetTextureParameterIiv"/>
+            <command name="glGetTextureParameterIuiv"/>
+            <command name="glGetTextureParameteriv"/>
+            <command name="glCreateVertexArrays"/>
+            <command name="glDisableVertexArrayAttrib"/>
+            <command name="glEnableVertexArrayAttrib"/>
+            <command name="glVertexArrayElementBuffer"/>
+            <command name="glVertexArrayVertexBuffer"/>
+            <command name="glVertexArrayVertexBuffers"/>
+            <command name="glVertexArrayAttribBinding"/>
+            <command name="glVertexArrayAttribFormat"/>
+            <command name="glVertexArrayAttribIFormat"/>
+            <command name="glVertexArrayAttribLFormat"/>
+            <command name="glVertexArrayBindingDivisor"/>
+            <command name="glGetVertexArrayiv"/>
+            <command name="glGetVertexArrayIndexediv"/>
+            <command name="glGetVertexArrayIndexed64iv"/>
+            <command name="glCreateSamplers"/>
+            <command name="glCreateProgramPipelines"/>
+            <command name="glCreateQueries"/>
+            <command name="glGetQueryBufferObjecti64v"/>
+            <command name="glGetQueryBufferObjectiv"/>
+            <command name="glGetQueryBufferObjectui64v"/>
+            <command name="glGetQueryBufferObjectuiv"/>
+        </require>
+        <require comment="Reuse GL_ARB_ES3_1_compatibility">
+            <enum name="GL_BACK"/>
+            <command name="glMemoryBarrierByRegion"/>
+        </require>
+        <require comment="Reuse GL_ARB_get_texture_sub_image">
+            <command name="glGetTextureSubImage"/>
+            <command name="glGetCompressedTextureSubImage"/>
+        </require>
+        <require comment="Reuse GL_ARB_robustness">
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_GUILTY_CONTEXT_RESET"/>
+            <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+            <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+            <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+            <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+            <enum name="GL_NO_RESET_NOTIFICATION"/>
+            <enum name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"/>
+            <enum name="GL_CONTEXT_LOST"/>
+            <command name="glGetGraphicsResetStatus"/>
+            <command name="glGetnCompressedTexImage"/>
+            <command name="glGetnTexImage"/>
+            <command name="glGetnUniformdv"/>
+            <command name="glGetnUniformfv"/>
+            <command name="glGetnUniformiv"/>
+            <command name="glGetnUniformuiv"/>
+            <command name="glReadnPixels"/>
+        </require>
+        <require profile="compatibility" comment="Reuse GL_ARB_robustness">
+            <command name="glGetnMapdv"/>
+            <command name="glGetnMapfv"/>
+            <command name="glGetnMapiv"/>
+            <command name="glGetnPixelMapfv"/>
+            <command name="glGetnPixelMapuiv"/>
+            <command name="glGetnPixelMapusv"/>
+            <command name="glGetnPolygonStipple"/>
+            <command name="glGetnColorTable"/>
+            <command name="glGetnConvolutionFilter"/>
+            <command name="glGetnSeparableFilter"/>
+            <command name="glGetnHistogram"/>
+            <command name="glGetnMinmax"/>
+        </require>
+        <require comment="Reuse GL_ARB_texture_barrier">
+            <command name="glTextureBarrier"/>
+        </require>
+        <require comment="Reuse GL_KHR_context_flush_control">
+            <enum name="GL_CONTEXT_RELEASE_BEHAVIOR"/>
+            <enum name="GL_NONE"/>
+            <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"/>
+        </require>
+    </feature>
 
     <!-- SECTION: OpenGL ES 1.0/1.1 API interface definitions. -->
     <feature api="gles1" name="GL_VERSION_ES_CM_1_0" number="1.0">
@@ -32313,6 +34983,22 @@
             <enum name="GL_COLOR_ATTACHMENT13"/>
             <enum name="GL_COLOR_ATTACHMENT14"/>
             <enum name="GL_COLOR_ATTACHMENT15"/>
+            <enum name="GL_COLOR_ATTACHMENT16"/>
+            <enum name="GL_COLOR_ATTACHMENT17"/>
+            <enum name="GL_COLOR_ATTACHMENT18"/>
+            <enum name="GL_COLOR_ATTACHMENT19"/>
+            <enum name="GL_COLOR_ATTACHMENT20"/>
+            <enum name="GL_COLOR_ATTACHMENT21"/>
+            <enum name="GL_COLOR_ATTACHMENT22"/>
+            <enum name="GL_COLOR_ATTACHMENT23"/>
+            <enum name="GL_COLOR_ATTACHMENT24"/>
+            <enum name="GL_COLOR_ATTACHMENT25"/>
+            <enum name="GL_COLOR_ATTACHMENT26"/>
+            <enum name="GL_COLOR_ATTACHMENT27"/>
+            <enum name="GL_COLOR_ATTACHMENT28"/>
+            <enum name="GL_COLOR_ATTACHMENT29"/>
+            <enum name="GL_COLOR_ATTACHMENT30"/>
+            <enum name="GL_COLOR_ATTACHMENT31"/>
             <enum name="GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"/>
             <enum name="GL_MAX_SAMPLES"/>
             <enum name="GL_HALF_FLOAT"/>
@@ -32832,6 +35518,332 @@
             <enum name="GL_MAX_VERTEX_ATTRIB_STRIDE"/>
         </require>
     </feature>
+    <feature api="gles2" name="GL_ES_VERSION_3_2" number="3.2">
+        <!-- 3.2-specific point features -->
+        <require>
+            <enum name="GL_MULTISAMPLE_LINE_WIDTH_RANGE"/>
+            <enum name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY"/>
+        </require>
+        <!-- Android extension pack features -->
+        <require/>
+        <!-- blend_equation_advanced features -->
+        <require>
+            <enum name="GL_MULTIPLY"/>
+            <enum name="GL_SCREEN"/>
+            <enum name="GL_OVERLAY"/>
+            <enum name="GL_DARKEN"/>
+            <enum name="GL_LIGHTEN"/>
+            <enum name="GL_COLORDODGE"/>
+            <enum name="GL_COLORBURN"/>
+            <enum name="GL_HARDLIGHT"/>
+            <enum name="GL_SOFTLIGHT"/>
+            <enum name="GL_DIFFERENCE"/>
+            <enum name="GL_EXCLUSION"/>
+            <enum name="GL_HSL_HUE"/>
+            <enum name="GL_HSL_SATURATION"/>
+            <enum name="GL_HSL_COLOR"/>
+            <enum name="GL_HSL_LUMINOSITY"/>
+            <command name="glBlendBarrier"/>
+        </require>
+        <!-- color_buffer_float features -->
+        <require/>
+        <!-- copy_image features -->
+        <require>
+            <command name="glCopyImageSubData"/>
+        </require>
+        <!-- debug features -->
+        <require>
+            <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS"/>
+            <enum name="GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH"/>
+            <enum name="GL_DEBUG_CALLBACK_FUNCTION"/>
+            <enum name="GL_DEBUG_CALLBACK_USER_PARAM"/>
+            <enum name="GL_DEBUG_SOURCE_API"/>
+            <enum name="GL_DEBUG_SOURCE_WINDOW_SYSTEM"/>
+            <enum name="GL_DEBUG_SOURCE_SHADER_COMPILER"/>
+            <enum name="GL_DEBUG_SOURCE_THIRD_PARTY"/>
+            <enum name="GL_DEBUG_SOURCE_APPLICATION"/>
+            <enum name="GL_DEBUG_SOURCE_OTHER"/>
+            <enum name="GL_DEBUG_TYPE_ERROR"/>
+            <enum name="GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR"/>
+            <enum name="GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR"/>
+            <enum name="GL_DEBUG_TYPE_PORTABILITY"/>
+            <enum name="GL_DEBUG_TYPE_PERFORMANCE"/>
+            <enum name="GL_DEBUG_TYPE_OTHER"/>
+            <enum name="GL_DEBUG_TYPE_MARKER"/>
+            <enum name="GL_DEBUG_TYPE_PUSH_GROUP"/>
+            <enum name="GL_DEBUG_TYPE_POP_GROUP"/>
+            <enum name="GL_DEBUG_SEVERITY_NOTIFICATION"/>
+            <enum name="GL_MAX_DEBUG_GROUP_STACK_DEPTH"/>
+            <enum name="GL_DEBUG_GROUP_STACK_DEPTH"/>
+            <enum name="GL_BUFFER"/>
+            <enum name="GL_SHADER"/>
+            <enum name="GL_PROGRAM"/>
+            <enum name="GL_VERTEX_ARRAY"/>
+            <enum name="GL_QUERY"/>
+            <enum name="GL_PROGRAM_PIPELINE"/>
+            <enum name="GL_SAMPLER"/>
+            <enum name="GL_MAX_LABEL_LENGTH"/>
+            <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
+            <enum name="GL_MAX_DEBUG_LOGGED_MESSAGES"/>
+            <enum name="GL_DEBUG_LOGGED_MESSAGES"/>
+            <enum name="GL_DEBUG_SEVERITY_HIGH"/>
+            <enum name="GL_DEBUG_SEVERITY_MEDIUM"/>
+            <enum name="GL_DEBUG_SEVERITY_LOW"/>
+            <enum name="GL_DEBUG_OUTPUT"/>
+            <enum name="GL_CONTEXT_FLAG_DEBUG_BIT"/>
+            <enum name="GL_STACK_OVERFLOW"/>
+            <enum name="GL_STACK_UNDERFLOW"/>
+            <command name="glDebugMessageControl"/>
+            <command name="glDebugMessageInsert"/>
+            <command name="glDebugMessageCallback"/>
+            <command name="glGetDebugMessageLog"/>
+            <command name="glPushDebugGroup"/>
+            <command name="glPopDebugGroup"/>
+            <command name="glObjectLabel"/>
+            <command name="glGetObjectLabel"/>
+            <command name="glObjectPtrLabel"/>
+            <command name="glGetObjectPtrLabel"/>
+            <command name="glGetPointerv"/>
+        </require>
+        <!-- draw_buffers_indexed features -->
+        <require>
+            <!-- All tokens are already part of ES 3.0 -->
+            <command name="glEnablei"/>
+            <command name="glDisablei"/>
+            <command name="glBlendEquationi"/>
+            <command name="glBlendEquationSeparatei"/>
+            <command name="glBlendFunci"/>
+            <command name="glBlendFuncSeparatei"/>
+            <command name="glColorMaski"/>
+            <command name="glIsEnabledi"/>
+        </require>
+        <!-- draw_elements_base_vertex features -->
+        <require>
+            <command name="glDrawElementsBaseVertex"/>
+            <command name="glDrawRangeElementsBaseVertex"/>
+            <command name="glDrawElementsInstancedBaseVertex"/>
+        </require>
+        <!-- geometry_shader features -->
+        <require>
+            <enum name="GL_GEOMETRY_SHADER"/>
+            <enum name="GL_GEOMETRY_SHADER_BIT"/>
+            <enum name="GL_GEOMETRY_VERTICES_OUT"/>
+            <enum name="GL_GEOMETRY_INPUT_TYPE"/>
+            <enum name="GL_GEOMETRY_OUTPUT_TYPE"/>
+            <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+            <enum name="GL_LAYER_PROVOKING_VERTEX"/>
+            <enum name="GL_LINES_ADJACENCY"/>
+            <enum name="GL_LINE_STRIP_ADJACENCY"/>
+            <enum name="GL_TRIANGLES_ADJACENCY"/>
+            <enum name="GL_TRIANGLE_STRIP_ADJACENCY"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES"/>
+            <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS"/>
+            <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_FIRST_VERTEX_CONVENTION"/>
+            <enum name="GL_LAST_VERTEX_CONVENTION"/>
+            <enum name="GL_UNDEFINED_VERTEX"/>
+            <enum name="GL_PRIMITIVES_GENERATED"/>
+            <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS"/>
+            <enum name="GL_MAX_FRAMEBUFFER_LAYERS"/>
+            <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS"/>
+            <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED"/>
+            <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER"/>
+            <command name="glFramebufferTexture"/>
+        </require>
+        <!-- gpu_shader5 features -->
+        <require/>
+        <!-- primitive_bounding_box features -->
+        <require>
+            <enum name="GL_PRIMITIVE_BOUNDING_BOX"/>
+            <command name="glPrimitiveBoundingBox"/>
+        </require>
+        <!-- robustness features -->
+        <require>
+            <enum name="GL_NO_ERROR"/>
+            <enum name="GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT"/>
+            <enum name="GL_CONTEXT_FLAGS"/>
+            <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+            <enum name="GL_GUILTY_CONTEXT_RESET"/>
+            <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+            <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+            <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+            <enum name="GL_NO_RESET_NOTIFICATION"/>
+            <enum name="GL_CONTEXT_LOST"/>
+            <command name="glGetGraphicsResetStatus"/>
+            <command name="glReadnPixels"/>
+            <command name="glGetnUniformfv"/>
+            <command name="glGetnUniformiv"/>
+            <command name="glGetnUniformuiv"/>
+        </require>
+        <!-- sample_shading features -->
+        <require>
+            <command name="glMinSampleShading"/>
+            <enum name="GL_SAMPLE_SHADING"/>
+            <enum name="GL_MIN_SAMPLE_SHADING_VALUE"/>
+        </require>
+        <!-- sample_variables features -->
+        <require/>
+        <!-- shader_image_atomic features -->
+        <require/>
+        <!-- shader_io_blocks features -->
+        <require/>
+        <!-- shader_multisample_interpolation features -->
+        <require>
+            <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET"/>
+            <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET"/>
+            <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS"/>
+        </require>
+        <!-- tessellation_shader features -->
+        <require>
+            <enum name="GL_PATCHES"/>
+            <enum name="GL_PATCH_VERTICES"/>
+            <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES"/>
+            <enum name="GL_TESS_GEN_MODE"/>
+            <enum name="GL_TESS_GEN_SPACING"/>
+            <enum name="GL_TESS_GEN_VERTEX_ORDER"/>
+            <enum name="GL_TESS_GEN_POINT_MODE"/>
+            <enum name="GL_TRIANGLES"/>
+            <enum name="GL_ISOLINES"/>
+            <enum name="GL_QUADS"/>
+            <enum name="GL_EQUAL"/>
+            <enum name="GL_FRACTIONAL_ODD"/>
+            <enum name="GL_FRACTIONAL_EVEN"/>
+            <enum name="GL_CCW"/>
+            <enum name="GL_CW"/>
+            <enum name="GL_MAX_PATCH_VERTICES"/>
+            <enum name="GL_MAX_TESS_GEN_LEVEL"/>
+            <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS"/>
+            <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_PATCH_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS"/>
+            <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS"/>
+            <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS"/>
+            <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS"/>
+            <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS"/>
+            <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS"/>
+            <enum name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED"/>
+            <enum name="GL_IS_PER_PATCH"/>
+            <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER"/>
+            <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_TESS_CONTROL_SHADER"/>
+            <enum name="GL_TESS_EVALUATION_SHADER"/>
+            <enum name="GL_TESS_CONTROL_SHADER_BIT"/>
+            <enum name="GL_TESS_EVALUATION_SHADER_BIT"/>
+            <command name="glPatchParameteri"/>
+        </require>
+        <!-- texture_border_clamp features -->
+        <require>
+            <enum name="GL_TEXTURE_BORDER_COLOR"/>
+            <enum name="GL_CLAMP_TO_BORDER"/>
+            <command name="glTexParameterIiv"/>
+            <command name="glTexParameterIuiv"/>
+            <command name="glGetTexParameterIiv"/>
+            <command name="glGetTexParameterIuiv"/>
+            <command name="glSamplerParameterIiv"/>
+            <command name="glSamplerParameterIuiv"/>
+            <command name="glGetSamplerParameterIiv"/>
+            <command name="glGetSamplerParameterIuiv"/>
+        </require>
+        <!-- texture_buffer features -->
+        <require>
+            <enum name="GL_TEXTURE_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_BINDING"/>
+            <enum name="GL_MAX_TEXTURE_BUFFER_SIZE"/>
+            <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING"/>
+            <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT"/>
+            <enum name="GL_SAMPLER_BUFFER"/>
+            <enum name="GL_INT_SAMPLER_BUFFER"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER"/>
+            <enum name="GL_IMAGE_BUFFER"/>
+            <enum name="GL_INT_IMAGE_BUFFER"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER"/>
+            <enum name="GL_TEXTURE_BUFFER_OFFSET"/>
+            <enum name="GL_TEXTURE_BUFFER_SIZE"/>
+            <command name="glTexBuffer"/>
+            <command name="glTexBufferRange"/>
+        </require>
+        <!-- texture_compression_astc_ldr features -->
+        <require>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_4x4"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_5x4"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_5x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_6x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_6x6"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_8x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_8x6"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_8x8"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x5"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x6"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x8"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_10x10"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_12x10"/>
+            <enum name="GL_COMPRESSED_RGBA_ASTC_12x12"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10"/>
+            <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12"/>
+        </require>
+        <!-- texture_cube_map_array features -->
+        <require>
+            <enum name="GL_TEXTURE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+            <enum name="GL_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW"/>
+            <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY"/>
+            <enum name="GL_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY"/>
+        </require>
+        <!-- texture_stencil8 features -->
+        <require>
+            <enum name="GL_STENCIL_INDEX"/>
+            <enum name="GL_STENCIL_INDEX8"/>
+        </require>
+        <!-- texture_storage_multisample_2d_array features -->
+        <require>
+            <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY"/>
+            <command name="glTexStorage3DMultisample"/>
+        </require>
+    </feature>
 
     <!-- SECTION: OpenGL / OpenGL ES extension interface definitions -->
     <extensions>
@@ -32910,6 +35922,7 @@
                 <command name="glBlendEquationSeparateIndexedAMD"/>
             </require>
         </extension>
+        <extension name="GL_AMD_gcn_shader" supported="gl"/>
         <extension name="GL_AMD_gpu_shader_int64" supported="gl">
             <require>
                 <enum name="GL_INT64_NV"/>
@@ -32992,7 +36005,6 @@
                 <command name="glVertexAttribParameteriAMD"/>
             </require>
         </extension>
-        <extension name="GL_AMD_gcn_shader" supported="gl"/>
         <extension name="GL_AMD_multi_draw_indirect" supported="gl">
             <require>
                 <command name="glMultiDrawArraysIndirectAMD"/>
@@ -33082,7 +36094,7 @@
                 <enum name="GL_VIRTUAL_PAGE_SIZE_Z_AMD"/>
                 <enum name="GL_MAX_SPARSE_TEXTURE_SIZE_AMD"/>
                 <enum name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_AMD"/>
-                <enum name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS"/>
+                <enum name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS" comment="Should have an AMD suffix, but probably too late now"/>
                 <enum name="GL_MIN_SPARSE_LEVEL_AMD"/>
                 <enum name="GL_MIN_LOD_WARNING_AMD"/>
                 <enum name="GL_TEXTURE_STORAGE_SPARSE_BIT_AMD"/>
@@ -33121,6 +36133,32 @@
             </require>
         </extension>
         <extension name="GL_AMD_vertex_shader_viewport_index" supported="gl"/>
+        <extension name="GL_ANDROID_extension_pack_es31a" supported="gles2">
+            <require comment="This is an alias for the following extensions. At present gl.xml doesn't actually replicate all their interfaces here.">
+                <!--
+                    KHR_debug
+                    KHR_texture_compression_astc_ldr
+                    KHR_blend_equation_advanced
+                    OES_sample_shading
+                    OES_sample_variables
+                    OES_shader_image_atomic
+                    OES_shader_multisample_interpolation
+                    OES_texture_stencil8
+                    OES_texture_storage_multisample_2d_array
+                    EXT_copy_image
+                    EXT_draw_buffers_indexed
+                    EXT_geometry_shader
+                    EXT_gpu_shader5
+                    EXT_primitive_bounding_box
+                    EXT_shader_io_blocks
+                    EXT_tessellation_shader
+                    EXT_texture_border_clamp
+                    EXT_texture_buffer
+                    EXT_texture_cube_map_array
+                    EXT_texture_srgb_decode
+                -->
+            </require>
+        </extension>
         <extension name="GL_ANGLE_depth_texture" supported="gles2">
             <require>
                 <enum name="GL_DEPTH_COMPONENT"/>
@@ -33200,6 +36238,20 @@
                 <enum name="GL_UNPACK_CLIENT_STORAGE_APPLE"/>
             </require>
         </extension>
+        <extension name="GL_APPLE_clip_distance" supported="gles2">
+            <require>
+                <enum name="GL_MAX_CLIP_DISTANCES_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE0_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE1_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE2_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE3_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE4_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE5_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE6_APPLE"/>
+                <enum name="GL_CLIP_DISTANCE7_APPLE"/>
+            </require>
+        </extension>
+        <extension name="GL_APPLE_color_buffer_packed_float" supported="gles2"/>
         <extension name="GL_APPLE_copy_texture_levels" supported="gles1|gles2">
             <require>
                 <command name="glCopyTextureLevelsAPPLE"/>
@@ -33345,6 +36397,14 @@
                 <enum name="GL_TEXTURE_MAX_LEVEL_APPLE"/>
             </require>
         </extension>
+        <extension name="GL_APPLE_texture_packed_float" supported="gles2">
+            <require>
+                <enum name="GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE"/>
+                <enum name="GL_UNSIGNED_INT_5_9_9_9_REV_APPLE"/>
+                <enum name="GL_R11F_G11F_B10F_APPLE"/>
+                <enum name="GL_RGB9_E5_APPLE"/>
+            </require>
+        </extension>
         <extension name="GL_APPLE_texture_range" supported="gl">
             <require>
                 <enum name="GL_TEXTURE_RANGE_LENGTH_APPLE"/>
@@ -33438,6 +36498,20 @@
                 <command name="glClearDepthf"/>
             </require>
         </extension>
+        <extension name="GL_ARB_ES3_1_compatibility" supported="gl|glcore">
+            <require>
+                <enum name="GL_BACK"/>
+                <command name="glMemoryBarrierByRegion"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_ES3_2_compatibility" supported="gl">
+            <require>
+                <enum name="GL_PRIMITIVE_BOUNDING_BOX_ARB"/>
+                <enum name="GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB"/>
+                <enum name="GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB"/>
+                <command name="glPrimitiveBoundingBoxARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_ES3_compatibility" supported="gl|glcore">
             <require>
                 <enum name="GL_COMPRESSED_RGB8_ETC2"/>
@@ -33529,6 +36603,17 @@
                 <command name="glClearTexSubImage"/>
             </require>
         </extension>
+        <extension name="GL_ARB_clip_control" supported="gl|glcore">
+            <require>
+                <command name="glClipControl"/>
+                <enum name="GL_LOWER_LEFT"/>
+                <enum name="GL_UPPER_LEFT"/>
+                <enum name="GL_NEGATIVE_ONE_TO_ONE"/>
+                <enum name="GL_ZERO_TO_ONE"/>
+                <enum name="GL_CLIP_ORIGIN"/>
+                <enum name="GL_CLIP_DEPTH_MODE"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_color_buffer_float" supported="gl">
             <require>
                 <enum name="GL_RGBA_FLOAT_MODE_ARB"/>
@@ -33588,12 +36673,18 @@
                 <command name="glDispatchComputeGroupSizeARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_conditional_render_inverted" supported="gl|glcore">
+            <require>
+                <enum name="GL_QUERY_WAIT_INVERTED"/>
+                <enum name="GL_QUERY_NO_WAIT_INVERTED"/>
+                <enum name="GL_QUERY_BY_REGION_WAIT_INVERTED"/>
+                <enum name="GL_QUERY_BY_REGION_NO_WAIT_INVERTED"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_conservative_depth" supported="gl|glcore"/>
         <extension name="GL_ARB_copy_buffer" supported="gl|glcore">
             <require>
-                <enum name="GL_COPY_READ_BUFFER_BINDING"/>
                 <enum name="GL_COPY_READ_BUFFER"/>
-                <enum name="GL_COPY_WRITE_BUFFER_BINDING"/>
                 <enum name="GL_COPY_WRITE_BUFFER"/>
                 <command name="glCopyBufferSubData"/>
             </require>
@@ -33603,6 +36694,12 @@
                 <command name="glCopyImageSubData"/>
             </require>
         </extension>
+        <extension name="GL_ARB_cull_distance" supported="gl|glcore">
+            <require>
+                <enum name="GL_MAX_CULL_DISTANCES"/>
+                <enum name="GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_debug_output" supported="gl|glcore">
             <require>
                 <enum name="GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB"/>
@@ -33654,6 +36751,139 @@
                 <enum name="GL_DEPTH_TEXTURE_MODE_ARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_derivative_control" supported="gl|glcore"/>
+        <extension name="GL_ARB_direct_state_access" supported="gl|glcore">
+            <require>
+                <enum name="GL_TEXTURE_TARGET"/>
+                <enum name="GL_QUERY_TARGET"/>
+                <enum name="GL_TEXTURE_BINDING_1D"/>
+                <enum name="GL_TEXTURE_BINDING_1D_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_2D"/>
+                <enum name="GL_TEXTURE_BINDING_2D_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_3D"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY"/>
+                <enum name="GL_TEXTURE_BINDING_RECTANGLE"/>
+            </require>
+            <require comment="Transform Feedback object functions">
+                <command name="glCreateTransformFeedbacks"/>
+                <command name="glTransformFeedbackBufferBase"/>
+                <command name="glTransformFeedbackBufferRange"/>
+                <command name="glGetTransformFeedbackiv"/>
+                <command name="glGetTransformFeedbacki_v"/>
+                <command name="glGetTransformFeedbacki64_v"/>
+            </require>
+            <require comment="Buffer object functions">
+                <command name="glCreateBuffers"/>
+                <command name="glNamedBufferStorage"/>
+                <command name="glNamedBufferData"/>
+                <command name="glNamedBufferSubData"/>
+                <command name="glCopyNamedBufferSubData"/>
+                <command name="glClearNamedBufferData"/>
+                <command name="glClearNamedBufferSubData"/>
+                <command name="glMapNamedBuffer"/>
+                <command name="glMapNamedBufferRange"/>
+                <command name="glUnmapNamedBuffer"/>
+                <command name="glFlushMappedNamedBufferRange"/>
+                <command name="glGetNamedBufferParameteriv"/>
+                <command name="glGetNamedBufferParameteri64v"/>
+                <command name="glGetNamedBufferPointerv"/>
+                <command name="glGetNamedBufferSubData"/>
+            </require>
+            <require comment="Framebuffer object functions">
+                <command name="glCreateFramebuffers"/>
+                <command name="glNamedFramebufferRenderbuffer"/>
+                <command name="glNamedFramebufferParameteri"/>
+                <command name="glNamedFramebufferTexture"/>
+                <command name="glNamedFramebufferTextureLayer"/>
+                <command name="glNamedFramebufferDrawBuffer"/>
+                <command name="glNamedFramebufferDrawBuffers"/>
+                <command name="glNamedFramebufferReadBuffer"/>
+                <command name="glInvalidateNamedFramebufferData"/>
+                <command name="glInvalidateNamedFramebufferSubData"/>
+                <command name="glClearNamedFramebufferiv"/>
+                <command name="glClearNamedFramebufferuiv"/>
+                <command name="glClearNamedFramebufferfv"/>
+                <command name="glClearNamedFramebufferfi"/>
+                <command name="glBlitNamedFramebuffer"/>
+                <command name="glCheckNamedFramebufferStatus"/>
+                <command name="glGetNamedFramebufferParameteriv"/>
+                <command name="glGetNamedFramebufferAttachmentParameteriv"/>
+            </require>
+            <require comment="Renderbuffer object functions">
+                <command name="glCreateRenderbuffers"/>
+                <command name="glNamedRenderbufferStorage"/>
+                <command name="glNamedRenderbufferStorageMultisample"/>
+                <command name="glGetNamedRenderbufferParameteriv"/>
+            </require>
+            <require comment="Texture object functions">
+                <command name="glCreateTextures"/>
+                <command name="glTextureBuffer"/>
+                <command name="glTextureBufferRange"/>
+                <command name="glTextureStorage1D"/>
+                <command name="glTextureStorage2D"/>
+                <command name="glTextureStorage3D"/>
+                <command name="glTextureStorage2DMultisample"/>
+                <command name="glTextureStorage3DMultisample"/>
+                <command name="glTextureSubImage1D"/>
+                <command name="glTextureSubImage2D"/>
+                <command name="glTextureSubImage3D"/>
+                <command name="glCompressedTextureSubImage1D"/>
+                <command name="glCompressedTextureSubImage2D"/>
+                <command name="glCompressedTextureSubImage3D"/>
+                <command name="glCopyTextureSubImage1D"/>
+                <command name="glCopyTextureSubImage2D"/>
+                <command name="glCopyTextureSubImage3D"/>
+                <command name="glTextureParameterf"/>
+                <command name="glTextureParameterfv"/>
+                <command name="glTextureParameteri"/>
+                <command name="glTextureParameterIiv"/>
+                <command name="glTextureParameterIuiv"/>
+                <command name="glTextureParameteriv"/>
+                <command name="glGenerateTextureMipmap"/>
+                <command name="glBindTextureUnit"/>
+                <command name="glGetTextureImage"/>
+                <command name="glGetCompressedTextureImage"/>
+                <command name="glGetTextureLevelParameterfv"/>
+                <command name="glGetTextureLevelParameteriv"/>
+                <command name="glGetTextureParameterfv"/>
+                <command name="glGetTextureParameterIiv"/>
+                <command name="glGetTextureParameterIuiv"/>
+                <command name="glGetTextureParameteriv"/>
+            </require>
+            <require comment="Vertex Array object functions">
+                <command name="glCreateVertexArrays"/>
+                <command name="glDisableVertexArrayAttrib"/>
+                <command name="glEnableVertexArrayAttrib"/>
+                <command name="glVertexArrayElementBuffer"/>
+                <command name="glVertexArrayVertexBuffer"/>
+                <command name="glVertexArrayVertexBuffers"/>
+                <command name="glVertexArrayAttribBinding"/>
+                <command name="glVertexArrayAttribFormat"/>
+                <command name="glVertexArrayAttribIFormat"/>
+                <command name="glVertexArrayAttribLFormat"/>
+                <command name="glVertexArrayBindingDivisor"/>
+                <command name="glGetVertexArrayiv"/>
+                <command name="glGetVertexArrayIndexediv"/>
+                <command name="glGetVertexArrayIndexed64iv"/>
+            </require>
+            <require comment="Sampler object functions">
+                <command name="glCreateSamplers"/>
+            </require>
+            <require comment="Program Pipeline object functions">
+                <command name="glCreateProgramPipelines"/>
+            </require>
+            <require comment="Query object functions">
+                <command name="glCreateQueries"/>
+                <command name="glGetQueryBufferObjecti64v"/>
+                <command name="glGetQueryBufferObjectiv"/>
+                <command name="glGetQueryBufferObjectui64v"/>
+                <command name="glGetQueryBufferObjectuiv"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_draw_buffers" supported="gl">
             <require>
                 <enum name="GL_MAX_DRAW_BUFFERS_ARB"/>
@@ -33833,6 +37063,7 @@
                 <enum name="GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_fragment_shader_interlock" supported="gl"/>
         <extension name="GL_ARB_framebuffer_no_attachments" supported="gl|glcore">
             <require>
                 <enum name="GL_FRAMEBUFFER_DEFAULT_WIDTH"/>
@@ -33867,11 +37098,6 @@
                 <enum name="GL_UNSIGNED_INT_24_8"/>
                 <enum name="GL_DEPTH24_STENCIL8"/>
                 <enum name="GL_TEXTURE_STENCIL_SIZE"/>
-                <enum name="GL_TEXTURE_RED_TYPE"/>
-                <enum name="GL_TEXTURE_GREEN_TYPE"/>
-                <enum name="GL_TEXTURE_BLUE_TYPE"/>
-                <enum name="GL_TEXTURE_ALPHA_TYPE"/>
-                <enum name="GL_TEXTURE_DEPTH_TYPE"/>
                 <enum name="GL_UNSIGNED_NORMALIZED"/>
                 <enum name="GL_FRAMEBUFFER_BINDING"/>
                 <enum name="GL_DRAW_FRAMEBUFFER_BINDING"/>
@@ -33950,8 +37176,6 @@
             </require>
             <require api="gl" profile="compatibility">
                 <enum name="GL_INDEX"/>
-                <enum name="GL_TEXTURE_LUMINANCE_TYPE"/>
-                <enum name="GL_TEXTURE_INTENSITY_TYPE"/>
             </require>
         </extension>
         <extension name="GL_ARB_framebuffer_sRGB" supported="gl|glcore">
@@ -33998,6 +37222,12 @@
                 <command name="glProgramParameteri"/>
             </require>
         </extension>
+        <extension name="GL_ARB_get_texture_sub_image" supported="gl|glcore">
+            <require>
+                <command name="glGetTextureSubImage"/>
+                <command name="glGetCompressedTextureSubImage"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_gpu_shader5" supported="gl|glcore">
             <require>
                 <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
@@ -34043,6 +37273,54 @@
                 <command name="glGetUniformdv"/>
             </require>
         </extension>
+        <extension name="GL_ARB_gpu_shader_int64" supported="gl">
+            <require>
+                <enum name="GL_INT64_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_ARB"/>
+                <enum name="GL_INT64_VEC2_ARB"/>
+                <enum name="GL_INT64_VEC3_ARB"/>
+                <enum name="GL_INT64_VEC4_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_VEC2_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_VEC3_ARB"/>
+                <enum name="GL_UNSIGNED_INT64_VEC4_ARB"/>
+                <command name="glUniform1i64ARB"/>
+                <command name="glUniform2i64ARB"/>
+                <command name="glUniform3i64ARB"/>
+                <command name="glUniform4i64ARB"/>
+                <command name="glUniform1i64vARB"/>
+                <command name="glUniform2i64vARB"/>
+                <command name="glUniform3i64vARB"/>
+                <command name="glUniform4i64vARB"/>
+                <command name="glUniform1ui64ARB"/>
+                <command name="glUniform2ui64ARB"/>
+                <command name="glUniform3ui64ARB"/>
+                <command name="glUniform4ui64ARB"/>
+                <command name="glUniform1ui64vARB"/>
+                <command name="glUniform2ui64vARB"/>
+                <command name="glUniform3ui64vARB"/>
+                <command name="glUniform4ui64vARB"/>
+                <command name="glGetUniformi64vARB"/>
+                <command name="glGetUniformui64vARB"/>
+                <command name="glGetnUniformi64vARB"/>
+                <command name="glGetnUniformui64vARB"/>
+                <command name="glProgramUniform1i64ARB"/>
+                <command name="glProgramUniform2i64ARB"/>
+                <command name="glProgramUniform3i64ARB"/>
+                <command name="glProgramUniform4i64ARB"/>
+                <command name="glProgramUniform1i64vARB"/>
+                <command name="glProgramUniform2i64vARB"/>
+                <command name="glProgramUniform3i64vARB"/>
+                <command name="glProgramUniform4i64vARB"/>
+                <command name="glProgramUniform1ui64ARB"/>
+                <command name="glProgramUniform2ui64ARB"/>
+                <command name="glProgramUniform3ui64ARB"/>
+                <command name="glProgramUniform4ui64ARB"/>
+                <command name="glProgramUniform1ui64vARB"/>
+                <command name="glProgramUniform2ui64vARB"/>
+                <command name="glProgramUniform3ui64vARB"/>
+                <command name="glProgramUniform4ui64vARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_half_float_pixel" supported="gl">
             <require>
                 <type name="GLhalfARB"/>
@@ -34481,6 +37759,28 @@
                 <enum name="GL_ANY_SAMPLES_PASSED"/>
             </require>
         </extension>
+        <extension name="GL_ARB_parallel_shader_compile" supported="gl">
+            <require>
+                <enum name="GL_MAX_SHADER_COMPILER_THREADS_ARB"/>
+                <enum name="GL_COMPLETION_STATUS_ARB"/>
+                <command name="glMaxShaderCompilerThreadsARB"/>
+            </require>
+        </extension>
+        <extension name="GL_ARB_pipeline_statistics_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_VERTICES_SUBMITTED_ARB"/>
+                <enum name="GL_PRIMITIVES_SUBMITTED_ARB"/>
+                <enum name="GL_VERTEX_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_TESS_CONTROL_SHADER_PATCHES_ARB"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_GEOMETRY_SHADER_INVOCATIONS"/>
+                <enum name="GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED_ARB"/>
+                <enum name="GL_FRAGMENT_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_COMPUTE_SHADER_INVOCATIONS_ARB"/>
+                <enum name="GL_CLIPPING_INPUT_PRIMITIVES_ARB"/>
+                <enum name="GL_CLIPPING_OUTPUT_PRIMITIVES_ARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_pixel_buffer_object" supported="gl">
             <require>
                 <enum name="GL_PIXEL_PACK_BUFFER_ARB"/>
@@ -34505,6 +37805,7 @@
                 <enum name="GL_COORD_REPLACE_ARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_post_depth_coverage" supported="gl"/>
         <extension name="GL_ARB_program_interface_query" supported="gl|glcore">
             <require>
                 <enum name="GL_UNIFORM"/>
@@ -34618,6 +37919,21 @@
             </require>
         </extension>
         <extension name="GL_ARB_robustness_isolation" supported="gl|glcore"/>
+        <extension name="GL_ARB_sample_locations" supported="gl">
+            <require>
+                <enum name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB"/>
+                <enum name="GL_SAMPLE_LOCATION_ARB"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB"/>
+                <enum name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB"/>
+                <enum name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB"/>
+                <command name="glFramebufferSampleLocationsfvARB"/>
+                <command name="glNamedFramebufferSampleLocationsfvARB"/>
+                <command name="glEvaluateDepthValuesARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_sample_shading" supported="gl|glcore">
             <require>
                 <enum name="GL_SAMPLE_SHADING_ARB"/>
@@ -34727,6 +38043,7 @@
                 <command name="glGetProgramPipelineInfoLog"/>
             </require>
         </extension>
+        <extension name="GL_ARB_shader_atomic_counter_ops" supported="gl"/>
         <extension name="GL_ARB_shader_atomic_counters" supported="gl|glcore">
             <require>
                 <enum name="GL_ATOMIC_COUNTER_BUFFER"/>
@@ -34761,7 +38078,9 @@
                 <command name="glGetActiveAtomicCounterBufferiv"/>
             </require>
         </extension>
+        <extension name="GL_ARB_shader_ballot" supported="gl"/>
         <extension name="GL_ARB_shader_bit_encoding" supported="gl|glcore"/>
+        <extension name="GL_ARB_shader_clock" supported="gl"/>
         <extension name="GL_ARB_shader_draw_parameters" supported="gl|glcore"/>
         <extension name="GL_ARB_shader_group_vote" supported="gl|glcore"/>
         <extension name="GL_ARB_shader_image_load_store" supported="gl|glcore">
@@ -34959,7 +38278,9 @@
                 <command name="glGetProgramStageiv"/>
             </require>
         </extension>
+        <extension name="GL_ARB_shader_texture_image_samples" supported="gl|glcore"/>
         <extension name="GL_ARB_shader_texture_lod" supported="gl"/>
+        <extension name="GL_ARB_shader_viewport_layer_array" supported="gl"/>
         <extension name="GL_ARB_shading_language_100" supported="gl">
             <require>
                 <enum name="GL_SHADING_LANGUAGE_VERSION_ARB"/>
@@ -34992,11 +38313,24 @@
                 <enum name="GL_TEXTURE_COMPARE_FAIL_VALUE_ARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_sparse_buffer" supported="gl|glcore">
+            <require>
+                <enum name="GL_SPARSE_STORAGE_BIT_ARB"/>
+                <enum name="GL_SPARSE_BUFFER_PAGE_SIZE_ARB"/>
+                <command name="glBufferPageCommitmentARB"/>
+            </require>
+            <require comment="Supported only if GL_EXT_direct_state_access is supported">
+                <command name="glNamedBufferPageCommitmentEXT"/>
+            </require>
+            <require comment="Supported only if GL_ARb_direct_state_access or GL 4.5 is supported">
+                <command name="glNamedBufferPageCommitmentARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_sparse_texture" supported="gl|glcore">
             <require>
                 <enum name="GL_TEXTURE_SPARSE_ARB"/>
                 <enum name="GL_VIRTUAL_PAGE_SIZE_INDEX_ARB"/>
-                <enum name="GL_MIN_SPARSE_LEVEL_ARB"/>
+                <enum name="GL_NUM_SPARSE_LEVELS_ARB"/>
                 <enum name="GL_NUM_VIRTUAL_PAGE_SIZES_ARB"/>
                 <enum name="GL_VIRTUAL_PAGE_SIZE_X_ARB"/>
                 <enum name="GL_VIRTUAL_PAGE_SIZE_Y_ARB"/>
@@ -35008,6 +38342,8 @@
                 <command name="glTexPageCommitmentARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_sparse_texture2" supported="gl"/>
+        <extension name="GL_ARB_sparse_texture_clamp" supported="gl"/>
         <extension name="GL_ARB_stencil_texturing" supported="gl|glcore">
             <require>
                 <enum name="GL_DEPTH_STENCIL_TEXTURE_MODE"/>
@@ -35082,6 +38418,11 @@
                 <command name="glPatchParameterfv"/>
             </require>
         </extension>
+        <extension name="GL_ARB_texture_barrier" supported="gl|glcore">
+            <require>
+                <command name="glTextureBarrier"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_texture_border_clamp" supported="gl">
             <require>
                 <enum name="GL_CLAMP_TO_BORDER_ARB"/>
@@ -35211,6 +38552,12 @@
                 <enum name="GL_DOT3_RGBA_ARB"/>
             </require>
         </extension>
+        <extension name="GL_ARB_texture_filter_minmax" supported="gl">
+            <require>
+                <enum name="GL_TEXTURE_REDUCTION_MODE_ARB"/>
+                <enum name="GL_WEIGHTED_AVERAGE_ARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_texture_float" supported="gl">
             <require>
                 <enum name="GL_TEXTURE_RED_TYPE_ARB"/>
@@ -35374,9 +38721,7 @@
         <extension name="GL_ARB_transform_feedback2" supported="gl|glcore">
             <require>
                 <enum name="GL_TRANSFORM_FEEDBACK"/>
-                <enum name="GL_TRANSFORM_FEEDBACK_PAUSED"/>
                 <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED"/>
-                <enum name="GL_TRANSFORM_FEEDBACK_ACTIVE"/>
                 <enum name="GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE"/>
                 <enum name="GL_TRANSFORM_FEEDBACK_BINDING"/>
                 <command name="glBindTransformFeedback"/>
@@ -35404,6 +38749,12 @@
                 <command name="glDrawTransformFeedbackStreamInstanced"/>
             </require>
         </extension>
+        <extension name="GL_ARB_transform_feedback_overflow_query" supported="gl|glcore">
+            <require>
+                <enum name="GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB"/>
+                <enum name="GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB"/>
+            </require>
+        </extension>
         <extension name="GL_ARB_transpose_matrix" supported="gl">
             <require>
                 <enum name="GL_TRANSPOSE_MODELVIEW_MATRIX_ARB"/>
@@ -35458,6 +38809,9 @@
                 <command name="glGetActiveUniformBlockiv"/>
                 <command name="glGetActiveUniformBlockName"/>
                 <command name="glUniformBlockBinding"/>
+                <command name="glBindBufferRange"/>
+                <command name="glBindBufferBase"/>
+                <command name="glGetIntegeri_v"/>
             </require>
         </extension>
         <extension name="GL_ARB_vertex_array_bgra" supported="gl|glcore">
@@ -36295,6 +39649,13 @@
                 <command name="glVertexBlendEnvfATI"/>
             </require>
         </extension>
+        <extension name="GL_DMP_program_binary" supported="gles2">
+            <require>
+                <enum name="GL_SMAPHS30_PROGRAM_BINARY_DMP"/>
+                <enum name="GL_SMAPHS_PROGRAM_BINARY_DMP"/>
+                <enum name="GL_DMP_PROGRAM_BINARY_DMP"/>
+            </require>
+        </extension>
         <extension name="GL_DMP_shader_binary" supported="gles2">
             <require>
                 <enum name="GL_SHADER_BINARY_DMP"/>
@@ -36308,11 +39669,26 @@
                 <enum name="GL_422_REV_AVERAGE_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_YUV_target" supported="gles2">
+            <require>
+                <enum name="GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT"/>
+                <enum name="GL_TEXTURE_EXTERNAL_OES"/>
+                <enum name="GL_TEXTURE_BINDING_EXTERNAL_OES"/>
+                <enum name="GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_abgr" supported="gl">
             <require>
                 <enum name="GL_ABGR_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_base_instance" supported="gles2">
+            <require>
+                <command name="glDrawArraysInstancedBaseInstanceEXT"/>
+                <command name="glDrawElementsInstancedBaseInstanceEXT"/>
+                <command name="glDrawElementsInstancedBaseVertexBaseInstanceEXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_bgra" supported="gl">
             <require>
                 <enum name="GL_BGR_EXT"/>
@@ -36349,6 +39725,21 @@
                 <command name="glBlendEquationSeparateEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_blend_func_extended" supported="gles2">
+            <require>
+                <enum name="GL_SRC1_COLOR_EXT"/>
+                <enum name="GL_SRC1_ALPHA_EXT"/>
+                <enum name="GL_ONE_MINUS_SRC1_COLOR_EXT"/>
+                <enum name="GL_ONE_MINUS_SRC1_ALPHA_EXT"/>
+                <enum name="GL_SRC_ALPHA_SATURATE_EXT"/>
+                <enum name="GL_LOCATION_INDEX_EXT"/>
+                <enum name="GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT"/>
+                <command name="glBindFragDataLocationIndexedEXT"/>
+                <command name="glBindFragDataLocationEXT"/>
+                <command name="glGetProgramResourceLocationIndexEXT"/>
+                <command name="glGetFragDataIndexEXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_blend_func_separate" supported="gl">
             <require>
                 <enum name="GL_BLEND_DST_RGB_EXT"/>
@@ -36376,6 +39767,21 @@
                 <enum name="GL_FUNC_REVERSE_SUBTRACT_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_buffer_storage" supported="gles2">
+            <require>
+                <enum name="GL_MAP_READ_BIT"/>
+                <enum name="GL_MAP_WRITE_BIT"/>
+                <enum name="GL_MAP_PERSISTENT_BIT_EXT"/>
+                <enum name="GL_MAP_COHERENT_BIT_EXT"/>
+                <enum name="GL_DYNAMIC_STORAGE_BIT_EXT"/>
+                <enum name="GL_CLIENT_STORAGE_BIT_EXT"/>
+                <enum name="GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT"/>
+                <enum name="GL_BUFFER_IMMUTABLE_STORAGE_EXT"/>
+                <enum name="GL_BUFFER_STORAGE_FLAGS_EXT"/>
+                <command name="glBufferStorageEXT"/>
+                <!-- <command name="glNamedBufferStorageEXT"/> -->
+            </require>
+        </extension>
         <extension name="GL_EXT_clip_volume_hint" supported="gl">
             <require>
                 <enum name="GL_CLIP_VOLUME_CLIPPING_HINT_EXT"/>
@@ -36389,6 +39795,7 @@
                 <enum name="GL_UNPACK_CMYK_HINT_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_color_buffer_float" supported="gles2"/>
         <extension name="GL_EXT_color_buffer_half_float" supported="gles2">
             <require>
                 <enum name="GL_RGBA16F_EXT"/>
@@ -37016,6 +40423,14 @@
                 <command name="glIsEnablediEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_draw_elements_base_vertex" supported="gles2">
+            <require>
+                <command name="glDrawElementsBaseVertexEXT"/>
+                <command name="glDrawRangeElementsBaseVertexEXT" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glDrawElementsInstancedBaseVertexEXT" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glMultiDrawElementsBaseVertexEXT" comment="Supported only if GL_EXT_multi_draw_arrays is supported"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_draw_instanced" supported="gl|gles2">
             <require>
                 <command name="glDrawArraysInstancedEXT"/>
@@ -37029,6 +40444,7 @@
                 <command name="glDrawRangeElementsEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_float_blend" supported="gles2"/>
         <extension name="GL_EXT_fog_coord" supported="gl">
             <require>
                 <enum name="GL_FOG_COORDINATE_SOURCE_EXT"/>
@@ -37147,6 +40563,7 @@
                 <enum name="GL_FRAMEBUFFER_SRGB_CAPABLE_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_geometry_point_size" supported="gles2"/>
         <extension name="GL_EXT_geometry_shader" supported="gles2">
             <require>
                 <enum name="GL_GEOMETRY_SHADER_EXT"/>
@@ -37259,9 +40676,7 @@
                 <command name="glUniform4uivEXT"/>
             </require>
         </extension>
-        <extension name="GL_EXT_gpu_shader5" supported="gles2">
-            <require/>
-        </extension>
+        <extension name="GL_EXT_gpu_shader5" supported="gles2"/>
         <extension name="GL_EXT_histogram" supported="gl">
             <require>
                 <enum name="GL_HISTOGRAM_EXT"/>
@@ -37363,6 +40778,12 @@
                 <command name="glMultiDrawElementsEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_multi_draw_indirect" supported="gles2">
+            <require>
+                <command name="glMultiDrawArraysIndirectEXT"/>
+                <command name="glMultiDrawElementsIndirectEXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_multisample" supported="gl">
             <require>
                 <enum name="GL_MULTISAMPLE_EXT"/>
@@ -37386,6 +40807,12 @@
                 <command name="glSamplePatternEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_multisampled_compatibility" supported="gles2">
+            <require>
+                <enum name="GL_MULTISAMPLE_EXT"/>
+                <enum name="GL_SAMPLE_ALPHA_TO_ONE_EXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_multisampled_render_to_texture" supported="gles1|gles2">
             <require>
                 <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT"/>
@@ -37509,6 +40936,13 @@
                 <command name="glPolygonOffsetEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_polygon_offset_clamp" supported="gl">
+            <require>
+                <enum name="GL_POLYGON_OFFSET_CLAMP_EXT"/>
+                <command name="glPolygonOffsetClampEXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_post_depth_coverage" supported="gl|gles2"/>
         <extension name="GL_EXT_primitive_bounding_box" supported="gles2">
             <require>
                 <enum name="GL_PRIMITIVE_BOUNDING_BOX_EXT"/>
@@ -37534,6 +40968,17 @@
                 <enum name="GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG"/>
             </require>
         </extension>
+        <extension name="GL_EXT_raster_multisample" supported="gl|gles2">
+            <require>
+                <enum name="GL_RASTER_MULTISAMPLE_EXT"/>
+                <enum name="GL_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_MAX_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+                <enum name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+                <enum name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+                <command name="glRasterSamplesEXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_read_format_bgra" supported="gles1|gles2">
             <require>
                 <enum name="GL_BGRA_EXT"/>
@@ -37541,6 +40986,18 @@
                 <enum name="GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_render_snorm" supported="gles2">
+            <require>
+                <enum name="GL_BYTE"/>
+                <enum name="GL_SHORT"/>
+                <enum name="GL_R8_SNORM"/>
+                <enum name="GL_RG8_SNORM"/>
+                <enum name="GL_RGBA8_SNORM"/>
+                <enum name="GL_R16_SNORM_EXT"/>
+                <enum name="GL_RG16_SNORM_EXT"/>
+                <enum name="GL_RGBA16_SNORM_EXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_rescale_normal" supported="gl">
             <require>
                 <enum name="GL_RESCALE_NORMAL_EXT"/>
@@ -37678,6 +41135,7 @@
                 <enum name="GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_shader_image_load_formatted" supported="gl"/>
         <extension name="GL_EXT_shader_image_load_store" supported="gl">
             <require>
                 <enum name="GL_MAX_IMAGE_UNITS_EXT"/>
@@ -37764,6 +41222,29 @@
                 <enum name="GL_SHARED_TEXTURE_PALETTE_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_sparse_texture" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_SPARSE_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_INDEX_EXT"/>
+                <enum name="GL_NUM_SPARSE_LEVELS_EXT"/>
+                <enum name="GL_NUM_VIRTUAL_PAGE_SIZES_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_X_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Y_EXT"/>
+                <enum name="GL_VIRTUAL_PAGE_SIZE_Z_EXT"/>
+                <enum name="GL_TEXTURE_2D"/>
+                <enum name="GL_TEXTURE_2D_ARRAY"/>
+                <enum name="GL_TEXTURE_CUBE_MAP"/>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_TEXTURE_3D"/>
+                <enum name="GL_MAX_SPARSE_TEXTURE_SIZE_EXT"/>
+                <enum name="GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT"/>
+                <enum name="GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT"/>
+                <enum name="GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT"/>
+                <command name="glTexPageCommitmentEXT"/>
+                <!-- <command name="glTexturePageCommitmentEXT"/> -->
+            </require>
+        </extension>
+        <extension name="GL_EXT_sparse_texture2" supported="gl"/>
         <extension name="GL_EXT_stencil_clear_tag" supported="gl">
             <require>
                 <enum name="GL_STENCIL_TAG_BITS_EXT"/>
@@ -37790,6 +41271,7 @@
                 <command name="glTexSubImage2DEXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_tessellation_point_size" supported="gles2"/>
         <extension name="GL_EXT_tessellation_shader" supported="gles2">
             <require>
                 <enum name="GL_PATCHES_EXT"/>
@@ -37799,7 +41281,7 @@
                 <enum name="GL_TESS_GEN_SPACING_EXT"/>
                 <enum name="GL_TESS_GEN_VERTEX_ORDER_EXT"/>
                 <enum name="GL_TESS_GEN_POINT_MODE_EXT"/>
-                <enum name="GL_TRIANGLES"/>                         
+                <enum name="GL_TRIANGLES"/>
                 <enum name="GL_ISOLINES_EXT"/>
                 <enum name="GL_QUADS_EXT"/>
                 <enum name="GL_EQUAL"/>
@@ -37915,6 +41397,7 @@
                 <enum name="GL_MAX_ARRAY_TEXTURE_LAYERS_EXT"/>
                 <enum name="GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT"/>
                 <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT"/>
+                <command name="glFramebufferTextureLayerEXT"/>
             </require>
         </extension>
         <extension name="GL_EXT_texture_border_clamp" supported="gles2">
@@ -38058,6 +41541,17 @@
                 <enum name="GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_texture_filter_minmax" supported="gl|gles2">
+            <require>
+                <enum name="GL_RASTER_MULTISAMPLE_EXT"/>
+                <enum name="GL_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_MAX_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+                <enum name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+                <enum name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+                <command name="glRasterSamplesEXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_texture_format_BGRA8888" supported="gles1|gles2">
             <require>
                 <enum name="GL_BGRA_EXT"/>
@@ -38134,6 +41628,18 @@
                 <enum name="GL_MIRROR_CLAMP_TO_BORDER_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_texture_norm16" supported="gles2">
+            <require>
+                <enum name="GL_R16_EXT"/>
+                <enum name="GL_RG16_EXT"/>
+                <enum name="GL_RGBA16_EXT"/>
+                <enum name="GL_RGB16_EXT"/>
+                <enum name="GL_R16_SNORM_EXT"/>
+                <enum name="GL_RG16_SNORM_EXT"/>
+                <enum name="GL_RGB16_SNORM_EXT"/>
+                <enum name="GL_RGBA16_SNORM_EXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_texture_object" supported="gl">
             <require>
                 <enum name="GL_TEXTURE_PRIORITY_EXT"/>
@@ -38184,6 +41690,16 @@
                 <enum name="GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT"/>
             </require>
         </extension>
+        <extension name="GL_EXT_texture_sRGB_R8" supported="gles2">
+            <require>
+                <enum name="GL_SR8_EXT"/>
+            </require>
+        </extension>
+        <extension name="GL_EXT_texture_sRGB_RG8" supported="gles2">
+            <require>
+                <enum name="GL_SRG8_EXT"/>
+            </require>
+        </extension>
         <extension name="GL_EXT_texture_sRGB_decode" supported="gl|gles2">
             <require>
                 <enum name="GL_TEXTURE_SRGB_DECODE_EXT"/>
@@ -38753,6 +42269,13 @@
                 <enum name="GL_DOT3_RGBA_IMG"/>
             </require>
         </extension>
+        <extension name="GL_IMG_texture_filter_cubic" supported="gles2">
+            <require>
+                <enum name="GL_CUBIC_IMG"/>
+                <enum name="GL_CUBIC_MIPMAP_NEAREST_IMG"/>
+                <enum name="GL_CUBIC_MIPMAP_LINEAR_IMG"/>
+            </require>
+        </extension>
         <extension name="GL_IMG_user_clip_plane" supported="gles1">
             <require>
                 <enum name="GL_CLIP_PLANE0_IMG"/>
@@ -38789,6 +42312,11 @@
             </require>
         </extension>
         <extension name="GL_INTEL_fragment_shader_ordering" supported="gl"/>
+        <extension name="GL_INTEL_framebuffer_CMAA" supported="gl|gles2">
+            <require>
+                <command name="glApplyFramebufferAttachmentCMAAINTEL"/>
+            </require>
+        </extension>
         <extension name="GL_INTEL_map_texture" supported="gl">
             <require>
                 <enum name="GL_TEXTURE_MEMORY_LAYOUT_INTEL"/>
@@ -38847,25 +42375,41 @@
                 <command name="glGetPerfQueryInfoINTEL"/>
             </require>
         </extension>
-        <extension name="GL_KHR_blend_equation_advanced" supported="gles2">
+        <extension name="GL_KHR_blend_equation_advanced" supported="gl|gles2">
             <require>
-                <command name="glBlendBarrierKHR"/>                                         
-                <enum name="GL_BLEND_ADVANCED_COHERENT_KHR"/>                               
-                <enum name="GL_MULTIPLY_KHR"/>                                              
-                <enum name="GL_SCREEN_KHR"/>                                                
-                <enum name="GL_OVERLAY_KHR"/>                                               
-                <enum name="GL_DARKEN_KHR"/>                                                
-                <enum name="GL_LIGHTEN_KHR"/>                                               
-                <enum name="GL_COLORDODGE_KHR"/>                                            
-                <enum name="GL_COLORBURN_KHR"/>                                             
-                <enum name="GL_HARDLIGHT_KHR"/>                                             
-                <enum name="GL_SOFTLIGHT_KHR"/>                                             
-                <enum name="GL_DIFFERENCE_KHR"/>                                            
-                <enum name="GL_EXCLUSION_KHR"/>                                             
-                <enum name="GL_HSL_HUE_KHR"/>                                               
-                <enum name="GL_HSL_SATURATION_KHR"/>                                        
-                <enum name="GL_HSL_COLOR_KHR"/>                                             
-                <enum name="GL_HSL_LUMINOSITY_KHR"/>                                        
+                <enum name="GL_MULTIPLY_KHR"/>
+                <enum name="GL_SCREEN_KHR"/>
+                <enum name="GL_OVERLAY_KHR"/>
+                <enum name="GL_DARKEN_KHR"/>
+                <enum name="GL_LIGHTEN_KHR"/>
+                <enum name="GL_COLORDODGE_KHR"/>
+                <enum name="GL_COLORBURN_KHR"/>
+                <enum name="GL_HARDLIGHT_KHR"/>
+                <enum name="GL_SOFTLIGHT_KHR"/>
+                <enum name="GL_DIFFERENCE_KHR"/>
+                <enum name="GL_EXCLUSION_KHR"/>
+                <enum name="GL_HSL_HUE_KHR"/>
+                <enum name="GL_HSL_SATURATION_KHR"/>
+                <enum name="GL_HSL_COLOR_KHR"/>
+                <enum name="GL_HSL_LUMINOSITY_KHR"/>
+                <command name="glBlendBarrierKHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_blend_equation_advanced_coherent" supported="gl|gles2">
+            <require comment="Otherwise identical to GL_KHR_blend_equation_advanced, just different semantic behavior">
+                <enum name="GL_BLEND_ADVANCED_COHERENT_KHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_context_flush_control" supported="gl|glcore|gles2">
+            <require api="gl" comment="KHR extensions *mandate* suffixes for ES, unlike for GL">
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR"/>
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH"/>
+                <enum name="GL_NONE"/>
+            </require>
+            <require api="gles2">
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_KHR"/>
+                <enum name="GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR"/>
+                <enum name="GL_NONE"/>
             </require>
         </extension>
         <extension name="GL_KHR_debug" supported="gl|glcore|gles2">
@@ -38897,6 +42441,7 @@
                 <enum name="GL_PROGRAM"/>
                 <enum name="GL_VERTEX_ARRAY"/>
                 <enum name="GL_QUERY"/>
+                <enum name="GL_PROGRAM_PIPELINE"/>
                 <enum name="GL_SAMPLER"/>
                 <enum name="GL_MAX_LABEL_LENGTH"/>
                 <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH"/>
@@ -38949,6 +42494,7 @@
                 <enum name="GL_PROGRAM_KHR"/>
                 <enum name="GL_VERTEX_ARRAY_KHR"/>
                 <enum name="GL_QUERY_KHR"/>
+                <enum name="GL_PROGRAM_PIPELINE_KHR"/>
                 <enum name="GL_SAMPLER_KHR"/>
                 <enum name="GL_MAX_LABEL_LENGTH_KHR"/>
                 <enum name="GL_MAX_DEBUG_MESSAGE_LENGTH_KHR"/>
@@ -38973,13 +42519,50 @@
                 <command name="glGetObjectPtrLabelKHR"/>
                 <command name="glGetPointervKHR"/>
             </require>
-            <require api="gl" comment="Could benefit from api/profile attributes at enum tag level">
-                <enum name="GL_PROGRAM_PIPELINE"/>
-            </require>
             <require api="gl" profile="compatibility">
                 <enum name="GL_DISPLAY_LIST"/>
             </require>
         </extension>
+        <extension name="GL_KHR_no_error" supported="gl|glcore|gles2">
+            <require>
+                <enum name="GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR"/>
+            </require>
+        </extension>
+        <extension name="GL_KHR_robust_buffer_access_behavior" supported="gl|glcore|gles2"/>
+        <extension name="GL_KHR_robustness" supported="gl|glcore|gles2">
+            <require api="gl" comment="KHR extensions *mandate* suffixes for ES, unlike for GL">
+                <enum name="GL_NO_ERROR"/>
+                <enum name="GL_CONTEXT_ROBUST_ACCESS"/>
+                <enum name="GL_LOSE_CONTEXT_ON_RESET"/>
+                <enum name="GL_GUILTY_CONTEXT_RESET"/>
+                <enum name="GL_INNOCENT_CONTEXT_RESET"/>
+                <enum name="GL_UNKNOWN_CONTEXT_RESET"/>
+                <enum name="GL_RESET_NOTIFICATION_STRATEGY"/>
+                <enum name="GL_NO_RESET_NOTIFICATION"/>
+                <enum name="GL_CONTEXT_LOST"/>
+                <command name="glGetGraphicsResetStatus"/>
+                <command name="glReadnPixels"/>
+                <command name="glGetnUniformfv"/>
+                <command name="glGetnUniformiv"/>
+                <command name="glGetnUniformuiv"/>
+            </require>
+            <require api="gles2">
+                <enum name="GL_NO_ERROR"/>
+                <enum name="GL_CONTEXT_ROBUST_ACCESS_KHR"/>
+                <enum name="GL_LOSE_CONTEXT_ON_RESET_KHR"/>
+                <enum name="GL_GUILTY_CONTEXT_RESET_KHR"/>
+                <enum name="GL_INNOCENT_CONTEXT_RESET_KHR"/>
+                <enum name="GL_UNKNOWN_CONTEXT_RESET_KHR"/>
+                <enum name="GL_RESET_NOTIFICATION_STRATEGY_KHR"/>
+                <enum name="GL_NO_RESET_NOTIFICATION_KHR"/>
+                <enum name="GL_CONTEXT_LOST_KHR"/>
+                <command name="glGetGraphicsResetStatusKHR"/>
+                <command name="glReadnPixelsKHR"/>
+                <command name="glGetnUniformfvKHR"/>
+                <command name="glGetnUniformivKHR"/>
+                <command name="glGetnUniformuivKHR"/>
+            </require>
+        </extension>
         <extension name="GL_KHR_texture_compression_astc_hdr" supported="gl|glcore|gles2">
             <require>
                 <enum name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
@@ -39044,6 +42627,7 @@
                 <enum name="GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR"/>
             </require>
         </extension>
+        <extension name="GL_KHR_texture_compression_astc_sliced_3d" supported="gl|glcore|gles2"/>
         <extension name="GL_MESAX_texture_stack" supported="gl">
             <require>
                 <enum name="GL_TEXTURE_1D_STACK_MESAX"/>
@@ -39120,7 +42704,13 @@
                 <command name="glMultiDrawElementsIndirectBindlessNV"/>
             </require>
         </extension>
-        <extension name="GL_NV_bindless_texture" supported="gl">
+        <extension name="GL_NV_bindless_multi_draw_indirect_count" supported="gl">
+            <require>
+                <command name="glMultiDrawArraysIndirectBindlessCountNV"/>
+                <command name="glMultiDrawElementsIndirectBindlessCountNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_bindless_texture" supported="gl|gles2">
             <require>
                 <command name="glGetTextureHandleNV"/>
                 <command name="glGetTextureSamplerHandleNV"/>
@@ -39200,13 +42790,53 @@
             </require>
         </extension>
         <extension name="GL_NV_blend_square" supported="gl"/>
+        <extension name="GL_NV_command_list" supported="gl">
+            <require>
+                <enum name="GL_TERMINATE_SEQUENCE_COMMAND_NV"/>
+                <enum name="GL_NOP_COMMAND_NV"/>
+                <enum name="GL_DRAW_ELEMENTS_COMMAND_NV"/>
+                <enum name="GL_DRAW_ARRAYS_COMMAND_NV"/>
+                <enum name="GL_DRAW_ELEMENTS_STRIP_COMMAND_NV"/>
+                <enum name="GL_DRAW_ARRAYS_STRIP_COMMAND_NV"/>
+                <enum name="GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV"/>
+                <enum name="GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV"/>
+                <enum name="GL_ELEMENT_ADDRESS_COMMAND_NV"/>
+                <enum name="GL_ATTRIBUTE_ADDRESS_COMMAND_NV"/>
+                <enum name="GL_UNIFORM_ADDRESS_COMMAND_NV"/>
+                <enum name="GL_BLEND_COLOR_COMMAND_NV"/>
+                <enum name="GL_STENCIL_REF_COMMAND_NV"/>
+                <enum name="GL_LINE_WIDTH_COMMAND_NV"/>
+                <enum name="GL_POLYGON_OFFSET_COMMAND_NV"/>
+                <enum name="GL_ALPHA_REF_COMMAND_NV"/>
+                <enum name="GL_VIEWPORT_COMMAND_NV"/>
+                <enum name="GL_SCISSOR_COMMAND_NV"/>
+                <enum name="GL_FRONT_FACE_COMMAND_NV"/>
+                <command name="glCreateStatesNV"/>
+                <command name="glDeleteStatesNV"/>
+                <command name="glIsStateNV"/>
+                <command name="glStateCaptureNV"/>
+                <command name="glGetCommandHeaderNV"/>
+                <command name="glGetStageIndexNV"/>
+                <command name="glDrawCommandsNV"/>
+                <command name="glDrawCommandsAddressNV"/>
+                <command name="glDrawCommandsStatesNV"/>
+                <command name="glDrawCommandsStatesAddressNV"/>
+                <command name="glCreateCommandListsNV"/>
+                <command name="glDeleteCommandListsNV"/>
+                <command name="glIsCommandListNV"/>
+                <command name="glListDrawCommandsStatesClientNV"/>
+                <command name="glCommandListSegmentsNV"/>
+                <command name="glCompileCommandListNV"/>
+                <command name="glCallCommandListNV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_compute_program5" supported="gl">
             <require>
                 <enum name="GL_COMPUTE_PROGRAM_NV"/>
                 <enum name="GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV"/>
             </require>
         </extension>
-        <extension name="GL_NV_conditional_render" supported="gl">
+        <extension name="GL_NV_conditional_render" supported="gl|gles2">
             <require>
                 <enum name="GL_QUERY_WAIT_NV"/>
                 <enum name="GL_QUERY_NO_WAIT_NV"/>
@@ -39216,6 +42846,23 @@
                 <command name="glEndConditionalRenderNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_conservative_raster" supported="gl|gles2">
+            <require>
+                <enum name="GL_CONSERVATIVE_RASTERIZATION_NV"/>
+                <enum name="GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV"/>
+                <enum name="GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV"/>
+                <enum name="GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV"/>
+                <command name="glSubpixelPrecisionBiasNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_conservative_raster_dilate" supported="gl">
+            <require>
+                <enum name="GL_CONSERVATIVE_RASTER_DILATE_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV"/>
+                <enum name="GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV"/>
+                <command name="glConservativeRasterParameterfNV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_copy_buffer" supported="gles2">
             <require>
                 <enum name="GL_COPY_READ_BUFFER_NV"/>
@@ -39415,6 +43062,11 @@
                 <command name="glSetFenceNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_fill_rectangle" supported="gl|gles2">
+            <require>
+                <enum name="GL_FILL_RECTANGLE_NV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_float_buffer" supported="gl">
             <require>
                 <enum name="GL_FLOAT_R_NV"/>
@@ -39442,6 +43094,13 @@
                 <enum name="GL_EYE_PLANE"/>
             </require>
         </extension>
+        <extension name="GL_NV_fragment_coverage_to_color" supported="gl|gles2">
+            <require>
+                <enum name="GL_FRAGMENT_COVERAGE_TO_COLOR_NV"/>
+                <enum name="GL_FRAGMENT_COVERAGE_COLOR_NV"/>
+                <command name="glFragmentCoverageColorNV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_fragment_program" supported="gl">
             <require>
                 <enum name="GL_MAX_FRAGMENT_PROGRAM_LOCAL_PARAMETERS_NV"/>
@@ -39471,6 +43130,7 @@
         </extension>
         <extension name="GL_NV_fragment_program4" supported="gl"/>
         <extension name="GL_NV_fragment_program_option" supported="gl"/>
+        <extension name="GL_NV_fragment_shader_interlock" supported="gl|gles2"/>
         <extension name="GL_NV_framebuffer_blit" supported="gles2">
             <require>
                 <enum name="GL_READ_FRAMEBUFFER_NV"/>
@@ -39480,6 +43140,28 @@
                 <command name="glBlitFramebufferNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_framebuffer_mixed_samples" supported="gl|gles2">
+            <require>
+                <enum name="GL_RASTER_MULTISAMPLE_EXT"/>
+                <enum name="GL_COVERAGE_MODULATION_TABLE_NV"/>
+                <enum name="GL_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_MAX_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT"/>
+                <enum name="GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT"/>
+                <enum name="GL_EFFECTIVE_RASTER_SAMPLES_EXT"/>
+                <enum name="GL_COLOR_SAMPLES_NV"/>
+                <enum name="GL_DEPTH_SAMPLES_NV"/>
+                <enum name="GL_STENCIL_SAMPLES_NV"/>
+                <enum name="GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV"/>
+                <enum name="GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV"/>
+                <enum name="GL_COVERAGE_MODULATION_NV"/>
+                <enum name="GL_COVERAGE_MODULATION_TABLE_SIZE_NV"/>
+                <command name="glRasterSamplesEXT"/>
+                <command name="glCoverageModulationTableNV"/>
+                <command name="glGetCoverageModulationTableNV"/>
+                <command name="glCoverageModulationNV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_framebuffer_multisample" supported="gles2">
             <require>
                 <enum name="GL_RENDERBUFFER_SAMPLES_NV"/>
@@ -39523,6 +43205,7 @@
             </require>
         </extension>
         <extension name="GL_NV_geometry_shader4" supported="gl"/>
+        <extension name="GL_NV_geometry_shader_passthrough" supported="gl|gles2"/>
         <extension name="GL_NV_gpu_program4" supported="gl">
             <require>
                 <enum name="GL_MIN_PROGRAM_TEXEL_OFFSET_NV"/>
@@ -39685,12 +43368,25 @@
                 <command name="glVertexAttribs4hvNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_image_formats" supported="gles2"/>
         <extension name="GL_NV_instanced_arrays" supported="gles2">
             <require>
                 <enum name="GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV"/>
                 <command name="glVertexAttribDivisorNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_internalformat_sample_query" supported="gl|gles2">
+            <require>
+                <enum name="GL_RENDERBUFFER"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE"/>
+                <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY"/>
+                <enum name="GL_MULTISAMPLES_NV"/>
+                <enum name="GL_SUPERSAMPLE_SCALE_X_NV"/>
+                <enum name="GL_SUPERSAMPLE_SCALE_Y_NV"/>
+                <enum name="GL_CONFORMANT_NV"/>
+                <command name="glGetInternalformatSampleivNV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_light_max_exponent" supported="gl">
             <require>
                 <enum name="GL_MAX_SHININESS_NV"/>
@@ -39758,7 +43454,7 @@
             </require>
         </extension>
         <extension name="GL_NV_parameter_buffer_object2" supported="gl"/>
-        <extension name="GL_NV_path_rendering" supported="gl">
+        <extension name="GL_NV_path_rendering" supported="gl|gles2">
             <require>
                 <enum name="GL_PATH_FORMAT_SVG_NV"/>
                 <enum name="GL_PATH_FORMAT_PS_NV"/>
@@ -39812,13 +43508,11 @@
                 <enum name="GL_SKIP_MISSING_GLYPH_NV"/>
                 <enum name="GL_USE_MISSING_GLYPH_NV"/>
                 <enum name="GL_PATH_ERROR_POSITION_NV"/>
-                <enum name="GL_PATH_FOG_GEN_MODE_NV"/>
                 <enum name="GL_ACCUM_ADJACENT_PAIRS_NV"/>
                 <enum name="GL_ADJACENT_PAIRS_NV"/>
                 <enum name="GL_FIRST_TO_REST_NV"/>
                 <enum name="GL_PATH_GEN_MODE_NV"/>
                 <enum name="GL_PATH_GEN_COEFF_NV"/>
-                <enum name="GL_PATH_GEN_COLOR_FORMAT_NV"/>
                 <enum name="GL_PATH_GEN_COMPONENTS_NV"/>
                 <enum name="GL_PATH_STENCIL_FUNC_NV"/>
                 <enum name="GL_PATH_STENCIL_REF_NV"/>
@@ -39887,9 +43581,6 @@
                 <enum name="GL_FONT_UNDERLINE_POSITION_BIT_NV"/>
                 <enum name="GL_FONT_UNDERLINE_THICKNESS_BIT_NV"/>
                 <enum name="GL_FONT_HAS_KERNING_BIT_NV"/>
-                <enum name="GL_PRIMARY_COLOR"/>
-                <enum name="GL_PRIMARY_COLOR_NV"/>
-                <enum name="GL_SECONDARY_COLOR_NV"/>
                 <command name="glGenPathsNV"/>
                 <command name="glDeletePathsNV"/>
                 <command name="glIsPathNV"/>
@@ -39916,9 +43607,6 @@
                 <command name="glStencilFillPathInstancedNV"/>
                 <command name="glStencilStrokePathInstancedNV"/>
                 <command name="glPathCoverDepthFuncNV"/>
-                <command name="glPathColorGenNV"/>
-                <command name="glPathTexGenNV"/>
-                <command name="glPathFogGenNV"/>
                 <command name="glCoverFillPathNV"/>
                 <command name="glCoverStrokePathNV"/>
                 <command name="glCoverFillPathInstancedNV"/>
@@ -39931,15 +43619,85 @@
                 <command name="glGetPathMetricsNV"/>
                 <command name="glGetPathMetricRangeNV"/>
                 <command name="glGetPathSpacingNV"/>
-                <command name="glGetPathColorGenivNV"/>
-                <command name="glGetPathColorGenfvNV"/>
-                <command name="glGetPathTexGenivNV"/>
-                <command name="glGetPathTexGenfvNV"/>
                 <command name="glIsPointInFillPathNV"/>
                 <command name="glIsPointInStrokePathNV"/>
                 <command name="glGetPathLengthNV"/>
                 <command name="glPointAlongPathNV"/>
             </require>
+            <require comment="API revision 1.2">
+                <enum name="GL_ROUNDED_RECT_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT_NV"/>
+                <enum name="GL_ROUNDED_RECT2_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT2_NV"/>
+                <enum name="GL_ROUNDED_RECT4_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT4_NV"/>
+                <enum name="GL_ROUNDED_RECT8_NV"/>
+                <enum name="GL_RELATIVE_ROUNDED_RECT8_NV"/>
+                <enum name="GL_RELATIVE_RECT_NV"/>
+                <enum name="GL_FONT_GLYPHS_AVAILABLE_NV"/>
+                <enum name="GL_FONT_TARGET_UNAVAILABLE_NV"/>
+                <enum name="GL_FONT_UNAVAILABLE_NV"/>
+                <enum name="GL_FONT_UNINTELLIGIBLE_NV"/>
+                <command name="glMatrixLoad3x2fNV"/>
+                <command name="glMatrixLoad3x3fNV"/>
+                <command name="glMatrixLoadTranspose3x3fNV"/>
+                <command name="glMatrixMult3x2fNV"/>
+                <command name="glMatrixMult3x3fNV"/>
+                <command name="glMatrixMultTranspose3x3fNV"/>
+                <command name="glStencilThenCoverFillPathNV"/>
+                <command name="glStencilThenCoverStrokePathNV"/>
+                <command name="glStencilThenCoverFillPathInstancedNV"/>
+                <command name="glStencilThenCoverStrokePathInstancedNV"/>
+                <command name="glPathGlyphIndexRangeNV"/>
+            </require>
+            <require comment="API revision 1.3">
+                <enum name="GL_CONIC_CURVE_TO_NV"/>
+                <enum name="GL_RELATIVE_CONIC_CURVE_TO_NV"/>
+                <enum name="GL_FONT_NUM_GLYPH_INDICES_BIT_NV"/>
+                <enum name="GL_STANDARD_FONT_FORMAT_NV"/>
+                <command name="glPathGlyphIndexArrayNV"/>
+                <command name="glPathMemoryGlyphIndexArrayNV"/>
+                <command name="glProgramPathFragmentInputGenNV"/>
+                <command name="glGetProgramResourcefvNV"/>
+            </require>
+            <require api="gl" profile="compatibility">
+                <enum name="GL_2_BYTES_NV"/>
+                <enum name="GL_3_BYTES_NV"/>
+                <enum name="GL_4_BYTES_NV"/>
+                <enum name="GL_EYE_LINEAR_NV"/>
+                <enum name="GL_OBJECT_LINEAR_NV"/>
+                <enum name="GL_CONSTANT_NV"/>
+                <enum name="GL_PATH_FOG_GEN_MODE_NV"/>
+                <enum name="GL_PRIMARY_COLOR"/>
+                <enum name="GL_PRIMARY_COLOR_NV"/>
+                <enum name="GL_SECONDARY_COLOR_NV"/>
+                <enum name="GL_PATH_GEN_COLOR_FORMAT_NV"/>
+                <command name="glPathColorGenNV"/>
+                <command name="glPathTexGenNV"/>
+                <command name="glPathFogGenNV"/>
+                <command name="glGetPathColorGenivNV"/>
+                <command name="glGetPathColorGenfvNV"/>
+                <command name="glGetPathTexGenivNV"/>
+                <command name="glGetPathTexGenfvNV"/>
+            </require>
+            <require comment="Other API additions of unknown history">
+                <enum name="GL_PATH_PROJECTION_NV"/>
+                <enum name="GL_PATH_MODELVIEW_NV"/>
+                <enum name="GL_PATH_MODELVIEW_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_MODELVIEW_MATRIX_NV"/>
+                <enum name="GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV"/>
+                <enum name="GL_PATH_PROJECTION_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_PROJECTION_MATRIX_NV"/>
+                <enum name="GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV"/>
+                <enum name="GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV"/>
+                <enum name="GL_FRAGMENT_INPUT_NV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_path_rendering_shared_edge" supported="gl|gles2">
+            <require>
+                <enum name="GL_SHARED_EDGE_NV"/>
+            </require>
         </extension>
         <extension name="GL_NV_pixel_data_range" supported="gl">
             <require>
@@ -39962,6 +43720,17 @@
                 <command name="glPointParameterivNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_polygon_mode" supported="gles2">
+            <require>
+                <enum name="GL_POLYGON_MODE_NV"/>
+                <enum name="GL_POLYGON_OFFSET_POINT_NV"/>
+                <enum name="GL_POLYGON_OFFSET_LINE_NV"/>
+                <enum name="GL_POINT_NV"/>
+                <enum name="GL_LINE_NV"/>
+                <enum name="GL_FILL_NV"/>
+                <command name="glPolygonModeNV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_present_video" supported="gl">
             <require>
                 <enum name="GL_FRAME_NV"/>
@@ -40090,8 +43859,26 @@
                 <enum name="GL_ETC1_SRGB8_NV"/>
             </require>
         </extension>
+        <extension name="GL_NV_sample_locations" supported="gl|gles2">
+            <require>
+                <enum name="GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV"/>
+                <enum name="GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV"/>
+                <enum name="GL_SAMPLE_LOCATION_NV"/>
+                <enum name="GL_PROGRAMMABLE_SAMPLE_LOCATION_NV"/>
+                <enum name="GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV"/>
+                <enum name="GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV"/>
+                <command name="glFramebufferSampleLocationsfvNV"/>
+                <command name="glNamedFramebufferSampleLocationsfvNV"/>
+                <command name="glResolveDepthValuesNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_sample_mask_override_coverage" supported="gl|gles2"/>
         <extension name="GL_NV_shader_atomic_counters" supported="gl"/>
         <extension name="GL_NV_shader_atomic_float" supported="gl"/>
+        <extension name="GL_NV_shader_atomic_fp16_vector" supported="gl"/>
+        <extension name="GL_NV_shader_atomic_int64" supported="gl"/>
         <extension name="GL_NV_shader_buffer_load" supported="gl">
             <require>
                 <enum name="GL_BUFFER_GPU_ADDRESS_NV"/>
@@ -40120,6 +43907,7 @@
                 <enum name="GL_WRITE_ONLY"/>
             </require>
         </extension>
+        <extension name="GL_NV_shader_noperspective_interpolation" supported="gles2"/>
         <extension name="GL_NV_shader_storage_buffer_object" supported="gl"/>
         <extension name="GL_NV_shader_thread_group" supported="gl">
             <require>
@@ -40129,7 +43917,6 @@
             </require>
         </extension>
         <extension name="GL_NV_shader_thread_shuffle" supported="gl"/>
-        <extension name="GL_EXT_shader_image_load_formatted" supported="gl"/>
         <extension name="GL_NV_shadow_samplers_array" supported="gles2">
             <require>
                 <enum name="GL_SAMPLER_2D_ARRAY_SHADOW_NV"/>
@@ -40379,6 +44166,13 @@
                 <command name="glDrawTransformFeedbackNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_uniform_buffer_unified_memory" supported="gl">
+            <require>
+                <enum name="GL_UNIFORM_BUFFER_UNIFIED_NV"/>
+                <enum name="GL_UNIFORM_BUFFER_ADDRESS_NV"/>
+                <enum name="GL_UNIFORM_BUFFER_LENGTH_NV"/>
+            </require>
+        </extension>
         <extension name="GL_NV_vdpau_interop" supported="gl">
             <require>
                 <enum name="GL_SURFACE_STATE_NV"/>
@@ -40716,6 +44510,31 @@
                 <command name="glVideoCaptureStreamParameterdvNV"/>
             </require>
         </extension>
+        <extension name="GL_NV_viewport_array" supported="gles2">
+            <require>
+                <enum name="GL_MAX_VIEWPORTS_NV"/>
+                <enum name="GL_VIEWPORT_SUBPIXEL_BITS_NV"/>
+                <enum name="GL_VIEWPORT_BOUNDS_RANGE_NV"/>
+                <enum name="GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV"/>
+                <enum name="GL_SCISSOR_BOX"/>
+                <enum name="GL_VIEWPORT"/>
+                <enum name="GL_DEPTH_RANGE"/>
+                <enum name="GL_SCISSOR_TEST"/>
+                <command name="glViewportArrayvNV"/>
+                <command name="glViewportIndexedfNV"/>
+                <command name="glViewportIndexedfvNV"/>
+                <command name="glScissorArrayvNV"/>
+                <command name="glScissorIndexedNV"/>
+                <command name="glScissorIndexedvNV"/>
+                <command name="glDepthRangeArrayfvNV"/>
+                <command name="glDepthRangeIndexedfNV"/>
+                <command name="glGetFloati_vNV"/>
+                <command name="glEnableiNV"/>
+                <command name="glDisableiNV"/>
+                <command name="glIsEnablediNV"/>
+            </require>
+        </extension>
+        <extension name="GL_NV_viewport_array2" supported="gl|gles2"/>
         <extension name="GL_OES_EGL_image" supported="gles1|gles2">
             <require>
                 <type name="GLeglImageOES"/>
@@ -40734,6 +44553,7 @@
                 <enum name="GL_SAMPLER_EXTERNAL_OES"/>
             </require>
         </extension>
+        <extension name="GL_OES_EGL_image_external_essl3" supported="gles2"/>
         <extension name="GL_OES_blend_equation_separate" supported="gles1">
             <require>
                 <enum name="GL_BLEND_EQUATION_RGB_OES"/>
@@ -40761,6 +44581,10 @@
         </extension>
         <extension name="GL_OES_byte_coordinates" supported="gl|gles1">
             <require>
+                <type name="GLbyte"/>
+                <enum name="GL_BYTE"/>
+            </require>
+            <require api="gl" comment="Immediate-mode entry points don't exist in ES 1.x">
                 <command name="glMultiTexCoord1bOES"/>
                 <command name="glMultiTexCoord1bvOES"/>
                 <command name="glMultiTexCoord2bOES"/>
@@ -40785,6 +44609,7 @@
                 <command name="glVertex4bvOES"/>
             </require>
         </extension>
+        <extension name="GL_OES_compressed_ETC1_RGB8_sub_texture" supported="gles1|gles2"/>
         <extension name="GL_OES_compressed_ETC1_RGB8_texture" supported="gles1|gles2">
             <require>
                 <enum name="GL_ETC1_RGB8_OES"/>
@@ -40804,6 +44629,11 @@
                 <enum name="GL_PALETTE8_RGB5_A1_OES"/>
             </require>
         </extension>
+        <extension name="GL_OES_copy_image" supported="gles2">
+            <require>
+                <command name="glCopyImageSubDataOES"/>
+            </require>
+        </extension>
         <extension name="GL_OES_depth24" supported="gles1|gles2">
             <require>
                 <enum name="GL_DEPTH_COMPONENT24_OES"/>
@@ -40821,6 +44651,54 @@
                 <enum name="GL_UNSIGNED_INT"/>
             </require>
         </extension>
+        <extension name="GL_OES_draw_buffers_indexed" supported="gles2">
+            <require>
+                <enum name="GL_BLEND_EQUATION_RGB"/>
+                <enum name="GL_BLEND_EQUATION_ALPHA"/>
+                <enum name="GL_BLEND_SRC_RGB"/>
+                <enum name="GL_BLEND_SRC_ALPHA"/>
+                <enum name="GL_BLEND_DST_RGB"/>
+                <enum name="GL_BLEND_DST_ALPHA"/>
+                <enum name="GL_COLOR_WRITEMASK"/>
+                <enum name="GL_BLEND"/>
+                <enum name="GL_FUNC_ADD"/>
+                <enum name="GL_FUNC_SUBTRACT"/>
+                <enum name="GL_FUNC_REVERSE_SUBTRACT"/>
+                <enum name="GL_MIN"/>
+                <enum name="GL_MAX"/>
+                <enum name="GL_ZERO"/>
+                <enum name="GL_ONE"/>
+                <enum name="GL_SRC_COLOR"/>
+                <enum name="GL_ONE_MINUS_SRC_COLOR"/>
+                <enum name="GL_DST_COLOR"/>
+                <enum name="GL_ONE_MINUS_DST_COLOR"/>
+                <enum name="GL_SRC_ALPHA"/>
+                <enum name="GL_ONE_MINUS_SRC_ALPHA"/>
+                <enum name="GL_DST_ALPHA"/>
+                <enum name="GL_ONE_MINUS_DST_ALPHA"/>
+                <enum name="GL_CONSTANT_COLOR"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_COLOR"/>
+                <enum name="GL_CONSTANT_ALPHA"/>
+                <enum name="GL_ONE_MINUS_CONSTANT_ALPHA"/>
+                <enum name="GL_SRC_ALPHA_SATURATE"/>
+                <command name="glEnableiOES"/>
+                <command name="glDisableiOES"/>
+                <command name="glBlendEquationiOES"/>
+                <command name="glBlendEquationSeparateiOES"/>
+                <command name="glBlendFunciOES"/>
+                <command name="glBlendFuncSeparateiOES"/>
+                <command name="glColorMaskiOES"/>
+                <command name="glIsEnablediOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_draw_elements_base_vertex" supported="gles2">
+            <require>
+                <command name="glDrawElementsBaseVertexOES"/>
+                <command name="glDrawRangeElementsBaseVertexOES" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glDrawElementsInstancedBaseVertexOES" comment="Supported only if OpenGL ES 3.0 is supported"/>
+                <command name="glMultiDrawElementsBaseVertexOES" comment="Supported only if GL_EXT_multi_draw_arrays is supported"/>
+            </require>
+        </extension>
         <extension name="GL_OES_draw_texture" supported="gles1">
             <require>
                 <enum name="GL_TEXTURE_CROP_RECT_OES"/>
@@ -40873,7 +44751,6 @@
                 <command name="glPointSizexOES"/>
                 <command name="glPolygonOffsetxOES"/>
                 <command name="glRotatexOES"/>
-                <command name="glSampleCoverageOES"/>
                 <command name="glScalexOES"/>
                 <command name="glTexEnvxOES"/>
                 <command name="glTexEnvxvOES"/>
@@ -41014,6 +44891,45 @@
                 <command name="glGenerateMipmapOES"/>
             </require>
         </extension>
+        <extension name="GL_OES_geometry_point_size" supported="gles2"/>
+        <extension name="GL_OES_geometry_shader" supported="gles2">
+            <require>
+                <enum name="GL_GEOMETRY_SHADER_OES"/>
+                <enum name="GL_GEOMETRY_SHADER_BIT_OES"/>
+                <enum name="GL_GEOMETRY_LINKED_VERTICES_OUT_OES"/>
+                <enum name="GL_GEOMETRY_LINKED_INPUT_TYPE_OES"/>
+                <enum name="GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES"/>
+                <enum name="GL_GEOMETRY_SHADER_INVOCATIONS_OES"/>
+                <enum name="GL_LAYER_PROVOKING_VERTEX_OES"/>
+                <enum name="GL_LINES_ADJACENCY_OES"/>
+                <enum name="GL_LINE_STRIP_ADJACENCY_OES"/>
+                <enum name="GL_TRIANGLES_ADJACENCY_OES"/>
+                <enum name="GL_TRIANGLE_STRIP_ADJACENCY_OES"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES"/>
+                <enum name="GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES"/>
+                <enum name="GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES"/>
+                <enum name="GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES"/>
+                <enum name="GL_FIRST_VERTEX_CONVENTION_OES"/>
+                <enum name="GL_LAST_VERTEX_CONVENTION_OES"/>
+                <enum name="GL_UNDEFINED_VERTEX_OES"/>
+                <enum name="GL_PRIMITIVES_GENERATED_OES"/>
+                <enum name="GL_FRAMEBUFFER_DEFAULT_LAYERS_OES"/>
+                <enum name="GL_MAX_FRAMEBUFFER_LAYERS_OES"/>
+                <enum name="GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES"/>
+                <enum name="GL_REFERENCED_BY_GEOMETRY_SHADER_OES"/>
+                <command name="glFramebufferTextureOES"/>
+            </require>
+        </extension>
         <extension name="GL_OES_get_program_binary" supported="gles2">
             <require>
                 <enum name="GL_PROGRAM_BINARY_LENGTH_OES"/>
@@ -41023,6 +44939,7 @@
                 <command name="glProgramBinaryOES"/>
             </require>
         </extension>
+        <extension name="GL_OES_gpu_shader5" supported="gles2"/>
         <extension name="GL_OES_mapbuffer" supported="gles1|gles2">
             <require>
                 <enum name="GL_WRITE_ONLY_OES"/>
@@ -41088,6 +45005,12 @@
                 <enum name="GL_COORD_REPLACE_OES"/>
             </require>
         </extension>
+        <extension name="GL_OES_primitive_bounding_box" supported="gles2">
+            <require>
+                <enum name="GL_PRIMITIVE_BOUNDING_BOX_OES"/>
+                <command name="glPrimitiveBoundingBoxOES"/>
+            </require>
+        </extension>
         <extension name="GL_OES_query_matrix" supported="gl|gles1">
             <require>
                 <command name="glQueryMatrixxOES"/>
@@ -41126,18 +45049,19 @@
         </extension>
         <extension name="GL_OES_sample_shading" supported="gles2">
             <require>
-                <command name="glMinSampleShadingOES"/>                                     
-                <enum name="GL_SAMPLE_SHADING_OES"/>                                        
-                <enum name="GL_MIN_SAMPLE_SHADING_VALUE_OES"/>                              
+                <command name="glMinSampleShadingOES"/>
+                <enum name="GL_SAMPLE_SHADING_OES"/>
+                <enum name="GL_MIN_SAMPLE_SHADING_VALUE_OES"/>
             </require>
         </extension>
         <extension name="GL_OES_sample_variables" supported="gles2"/>
         <extension name="GL_OES_shader_image_atomic" supported="gles2"/>
+        <extension name="GL_OES_shader_io_blocks" supported="gles2"/>
         <extension name="GL_OES_shader_multisample_interpolation" supported="gles2">
             <require>
-                <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES"/>                     
-                <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES"/>                     
-                <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES"/>                    
+                <enum name="GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
+                <enum name="GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES"/>
+                <enum name="GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES"/>
             </require>
         </extension>
         <extension name="GL_OES_single_precision" supported="gl|gles1">
@@ -41181,6 +45105,59 @@
                 <enum name="GL_FRAMEBUFFER_UNDEFINED_OES"/>
             </require>
         </extension>
+        <extension name="GL_OES_tessellation_point_size" supported="gles2"/>
+        <extension name="GL_OES_tessellation_shader" supported="gles2">
+            <require>
+                <enum name="GL_PATCHES_OES"/>
+                <enum name="GL_PATCH_VERTICES_OES"/>
+                <enum name="GL_TESS_CONTROL_OUTPUT_VERTICES_OES"/>
+                <enum name="GL_TESS_GEN_MODE_OES"/>
+                <enum name="GL_TESS_GEN_SPACING_OES"/>
+                <enum name="GL_TESS_GEN_VERTEX_ORDER_OES"/>
+                <enum name="GL_TESS_GEN_POINT_MODE_OES"/>
+                <enum name="GL_TRIANGLES"/>
+                <enum name="GL_ISOLINES_OES"/>
+                <enum name="GL_QUADS_OES"/>
+                <enum name="GL_EQUAL"/>
+                <enum name="GL_FRACTIONAL_ODD_OES"/>
+                <enum name="GL_FRACTIONAL_EVEN_OES"/>
+                <enum name="GL_CCW"/>
+                <enum name="GL_CW"/>
+                <enum name="GL_MAX_PATCH_VERTICES_OES"/>
+                <enum name="GL_MAX_TESS_GEN_LEVEL_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_PATCH_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES"/>
+                <enum name="GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES"/>
+                <enum name="GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES"/>
+                <enum name="GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES"/>
+                <enum name="GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES"/>
+                <enum name="GL_IS_PER_PATCH_OES"/>
+                <enum name="GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES"/>
+                <enum name="GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES"/>
+                <enum name="GL_TESS_CONTROL_SHADER_OES"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_OES"/>
+                <enum name="GL_TESS_CONTROL_SHADER_BIT_OES"/>
+                <enum name="GL_TESS_EVALUATION_SHADER_BIT_OES"/>
+                <command name="glPatchParameteriOES"/>
+            </require>
+        </extension>
         <extension name="GL_OES_texture_3D" supported="gles2">
             <require>
                 <enum name="GL_TEXTURE_WRAP_R_OES"/>
@@ -41197,6 +45174,40 @@
                 <command name="glFramebufferTexture3DOES"/>
             </require>
         </extension>
+        <extension name="GL_OES_texture_border_clamp" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BORDER_COLOR_OES"/>
+                <enum name="GL_CLAMP_TO_BORDER_OES"/>
+                <command name="glTexParameterIivOES"/>
+                <command name="glTexParameterIuivOES"/>
+                <command name="glGetTexParameterIivOES"/>
+                <command name="glGetTexParameterIuivOES"/>
+                <command name="glSamplerParameterIivOES"/>
+                <command name="glSamplerParameterIuivOES"/>
+                <command name="glGetSamplerParameterIivOES"/>
+                <command name="glGetSamplerParameterIuivOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_buffer" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_BUFFER_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_BINDING_OES"/>
+                <enum name="GL_MAX_TEXTURE_BUFFER_SIZE_OES"/>
+                <enum name="GL_TEXTURE_BINDING_BUFFER_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES"/>
+                <enum name="GL_SAMPLER_BUFFER_OES"/>
+                <enum name="GL_INT_SAMPLER_BUFFER_OES"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_BUFFER_OES"/>
+                <enum name="GL_IMAGE_BUFFER_OES"/>
+                <enum name="GL_INT_IMAGE_BUFFER_OES"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_BUFFER_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_OFFSET_OES"/>
+                <enum name="GL_TEXTURE_BUFFER_SIZE_OES"/>
+                <command name="glTexBufferOES"/>
+                <command name="glTexBufferRangeOES"/>
+            </require>
+        </extension>
         <extension name="GL_OES_texture_compression_astc" supported="gles2" comment="API is identical to GL_KHR_texture_compression_astc_hdr extension">
             <require>
                 <enum name="GL_COMPRESSED_RGBA_ASTC_4x4_KHR"/>
@@ -41275,6 +45286,19 @@
                 <command name="glGetTexGenxvOES"/>
             </require>
         </extension>
+        <extension name="GL_OES_texture_cube_map_array" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES"/>
+                <enum name="GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_IMAGE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
+                <enum name="GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES"/>
+            </require>
+        </extension>
         <extension name="GL_OES_texture_env_crossbar" supported="gles1"/>
         <extension name="GL_OES_texture_float" supported="gles2">
             <require>
@@ -41296,18 +45320,28 @@
         <extension name="GL_OES_texture_npot" supported="gles2"/>
         <extension name="GL_OES_texture_stencil8" supported="gles2">
             <require>
-                <enum name="GL_STENCIL_INDEX_OES"/>                                         
-                <enum name="GL_STENCIL_INDEX8_OES"/>                                        
+                <enum name="GL_STENCIL_INDEX_OES"/>
+                <enum name="GL_STENCIL_INDEX8_OES"/>
             </require>
         </extension>
         <extension name="GL_OES_texture_storage_multisample_2d_array" supported="gles2">
             <require>
-                <command name="glTexStorage3DMultisampleOES"/>
                 <enum name="GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES"/>
                 <enum name="GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES"/>
                 <enum name="GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
                 <enum name="GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
                 <enum name="GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES"/>
+                <command name="glTexStorage3DMultisampleOES"/>
+            </require>
+        </extension>
+        <extension name="GL_OES_texture_view" supported="gles2">
+            <require>
+                <enum name="GL_TEXTURE_VIEW_MIN_LEVEL_OES"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LEVELS_OES"/>
+                <enum name="GL_TEXTURE_VIEW_MIN_LAYER_OES"/>
+                <enum name="GL_TEXTURE_VIEW_NUM_LAYERS_OES"/>
+                <enum name="GL_TEXTURE_IMMUTABLE_LEVELS"/>
+                <command name="glTextureViewOES"/>
             </require>
         </extension>
         <extension name="GL_OES_vertex_array_object" supported="gles1|gles2">
@@ -41352,6 +45386,20 @@
                 <enum name="GL_FORMAT_SUBSAMPLE_244_244_OML"/>
             </require>
         </extension>
+        <extension name="GL_OVR_multiview" supported="gl|gles2">
+            <require>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR"/>
+                <enum name="GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR"/>
+                <enum name="GL_MAX_VIEWS_OVR"/>
+                <command name="glFramebufferTextureMultiviewOVR"/>
+            </require>
+        </extension>
+        <extension name="GL_OVR_multiview2" supported="gl|gles2"/>
+        <extension name="GL_OVR_multiview_multisampled_render_to_texture" supported="gles2">
+            <require>
+                <command name="glFramebufferTextureMultisampleMultiviewOVR"/>
+            </require>
+        </extension>
         <extension name="GL_PGI_misc_hints" supported="gl">
             <require>
                 <enum name="GL_PREFER_DOUBLEBUFFER_HINT_PGI"/>
diff --git a/opengl/tools/glgen2/registry/reg.py b/opengl/tools/glgen2/registry/reg.py
index 1bbe0a0..9248b66 100755
--- a/opengl/tools/glgen2/registry/reg.py
+++ b/opengl/tools/glgen2/registry/reg.py
@@ -222,7 +222,7 @@
 #     the <extension>. Defaults to None. Usually the same as apiname.
 #   addExtensions - regex matching names of additional extensions
 #     to include. Defaults to None.
-#   removeExtenions - regex matching names of extensions to
+#   removeExtensions - regex matching names of extensions to
 #     remove (after defaultExtensions and addExtensions). Defaults
 #     to None.
 #   sortProcedure - takes a list of FeatureInfo objects and sorts
diff --git a/services/batteryservice/BatteryProperties.cpp b/services/batteryservice/BatteryProperties.cpp
index f13d6e8..d89d4c9 100644
--- a/services/batteryservice/BatteryProperties.cpp
+++ b/services/batteryservice/BatteryProperties.cpp
@@ -34,12 +34,14 @@
     chargerUsbOnline = p->readInt32() == 1 ? true : false;
     chargerWirelessOnline = p->readInt32() == 1 ? true : false;
     maxChargingCurrent = p->readInt32();
+    maxChargingVoltage = p->readInt32();
     batteryStatus = p->readInt32();
     batteryHealth = p->readInt32();
     batteryPresent = p->readInt32() == 1 ? true : false;
     batteryLevel = p->readInt32();
     batteryVoltage = p->readInt32();
     batteryTemperature = p->readInt32();
+    batteryChargeCounter = p->readInt32();
     batteryTechnology = String8((p->readString16()).string());
     return OK;
 }
@@ -49,12 +51,14 @@
     p->writeInt32(chargerUsbOnline ? 1 : 0);
     p->writeInt32(chargerWirelessOnline ? 1 : 0);
     p->writeInt32(maxChargingCurrent);
+    p->writeInt32(maxChargingVoltage);
     p->writeInt32(batteryStatus);
     p->writeInt32(batteryHealth);
     p->writeInt32(batteryPresent ? 1 : 0);
     p->writeInt32(batteryLevel);
     p->writeInt32(batteryVoltage);
     p->writeInt32(batteryTemperature);
+    p->writeInt32(batteryChargeCounter);
     p->writeString16(String16(batteryTechnology));
     return OK;
 }
diff --git a/services/inputflinger/EventHub.cpp b/services/inputflinger/EventHub.cpp
index 5859606..2a53dec 100644
--- a/services/inputflinger/EventHub.cpp
+++ b/services/inputflinger/EventHub.cpp
@@ -1191,6 +1191,15 @@
         device->classes |= INPUT_DEVICE_CLASS_CURSOR;
     }
 
+    // See if this is a rotary encoder type device.
+    String8 deviceType = String8();
+    if (device->configuration &&
+        device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
+            if (!deviceType.compare(String8("rotaryEncoder"))) {
+                device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
+            }
+    }
+
     // See if this is a touch pad.
     // Is this a new modern multi-touch driver?
     if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
diff --git a/services/inputflinger/EventHub.h b/services/inputflinger/EventHub.h
index 0f94c77..6869253 100644
--- a/services/inputflinger/EventHub.h
+++ b/services/inputflinger/EventHub.h
@@ -137,6 +137,9 @@
     /* The input device is an external stylus (has data we want to fuse with touch data). */
     INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
 
+    /* The input device has a rotary encoder */
+    INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
+
     /* The input device is virtual (not a real device, not part of UI configuration). */
     INPUT_DEVICE_CLASS_VIRTUAL       = 0x40000000,
 
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index c9e876f..3f69d49 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -134,7 +134,7 @@
     case AMOTION_EVENT_ACTION_POINTER_DOWN:
     case AMOTION_EVENT_ACTION_POINTER_UP: {
         int32_t index = getMotionEventActionPointerIndex(action);
-        return index >= 0 && size_t(index) < pointerCount;
+        return index >= 0 && index < pointerCount;
     }
     case AMOTION_EVENT_ACTION_BUTTON_PRESS:
     case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
@@ -902,7 +902,7 @@
         ALOGD("  Pointer %d: id=%d, toolType=%d, "
                 "x=%f, y=%f, pressure=%f, size=%f, "
                 "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
-                "orientation=%f",
+                "orientation=%f, relativeX=%f, relativeY=%f",
                 i, entry->pointerProperties[i].id,
                 entry->pointerProperties[i].toolType,
                 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
@@ -913,7 +913,9 @@
                 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
                 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
                 entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
-                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X),
+                entry->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y));
     }
 #endif
 }
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index b2cbfe8..374a5de 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -450,6 +450,11 @@
         device->addMapper(new SwitchInputMapper(device));
     }
 
+    // Scroll wheel-like devices.
+    if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
+        device->addMapper(new RotaryEncoderInputMapper(device));
+    }
+
     // Vibrator-like devices.
     if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
         device->addMapper(new VibratorInputMapper(device));
@@ -692,6 +697,21 @@
     return result;
 }
 
+void InputReader::toggleCapsLockState(int32_t deviceId) {
+    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
+    if (deviceIndex < 0) {
+        ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
+        return;
+    }
+
+    InputDevice* device = mDevices.valueAt(deviceIndex);
+    if (device->isIgnored()) {
+        return;
+    }
+
+    device->updateMetaState(AKEYCODE_CAPS_LOCK);
+}
+
 bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
         size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
     AutoMutex _l(mLock);
@@ -1167,6 +1187,13 @@
     return result;
 }
 
+void InputDevice::updateMetaState(int32_t keyCode) {
+    size_t numMappers = mMappers.size();
+    for (size_t i = 0; i < numMappers; i++) {
+        mMappers[i]->updateMetaState(keyCode);
+    }
+}
+
 void InputDevice::fadePointer() {
     size_t numMappers = mMappers.size();
     for (size_t i = 0; i < numMappers; i++) {
@@ -1875,6 +1902,9 @@
     return 0;
 }
 
+void InputMapper::updateMetaState(int32_t keyCode) {
+}
+
 void InputMapper::updateExternalStylusState(const StylusState& state) {
 
 }
@@ -2260,18 +2290,12 @@
         }
     }
 
-    int32_t oldMetaState = mMetaState;
-    int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
-    bool metaStateChanged = oldMetaState != newMetaState;
-    if (metaStateChanged) {
-        mMetaState = newMetaState;
-        updateLedState(false);
-
+    if (updateMetaStateIfNeeded(keyCode, down)) {
         // If global meta state changed send it along with the key.
         // If it has not changed then we'll use what keymap gave us,
         // since key replacement logic might temporarily reset a few
         // meta bits for given key.
-        keyMetaState = newMetaState;
+        keyMetaState = mMetaState;
     }
 
     nsecs_t downTime = mDownTime;
@@ -2289,10 +2313,6 @@
         policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
     }
 
-    if (metaStateChanged) {
-        getContext()->updateGlobalMetaState();
-    }
-
     if (down && !isMetaKey(keyCode)) {
         getContext()->fadePointer();
     }
@@ -2330,6 +2350,24 @@
     return mMetaState;
 }
 
+void KeyboardInputMapper::updateMetaState(int32_t keyCode) {
+    updateMetaStateIfNeeded(keyCode, false);
+}
+
+bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
+    int32_t oldMetaState = mMetaState;
+    int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
+    bool metaStateChanged = oldMetaState != newMetaState;
+    if (metaStateChanged) {
+        mMetaState = newMetaState;
+        updateLedState(false);
+
+        getContext()->updateGlobalMetaState();
+    }
+
+    return metaStateChanged;
+}
+
 void KeyboardInputMapper::resetLedState() {
     initializeLedState(mCapsLockLedState, ALED_CAPS_LOCK);
     initializeLedState(mNumLockLedState, ALED_NUM_LOCK);
@@ -2609,6 +2647,8 @@
         mPointerController->getPosition(&x, &y);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
         displayId = ADISPLAY_ID_DEFAULT;
     } else {
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
@@ -2728,6 +2768,103 @@
     }
 }
 
+// --- RotaryEncoderInputMapper ---
+
+RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
+        InputMapper(device) {
+    mSource = AINPUT_SOURCE_ROTARY_ENCODER;
+}
+
+RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
+}
+
+uint32_t RotaryEncoderInputMapper::getSources() {
+    return mSource;
+}
+
+void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+    InputMapper::populateDeviceInfo(info);
+
+    if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
+        float res = 0.0f;
+        if (!mDevice->getConfiguration().tryGetProperty(String8("device.res"), res)) {
+            ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
+        }
+        if (!mDevice->getConfiguration().tryGetProperty(String8("device.scalingFactor"),
+            mScalingFactor)) {
+            ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
+              "default to 1.0!\n");
+            mScalingFactor = 1.0f;
+        }
+        info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
+            res * mScalingFactor);
+    }
+}
+
+void RotaryEncoderInputMapper::dump(String8& dump) {
+    dump.append(INDENT2 "Rotary Encoder Input Mapper:\n");
+    dump.appendFormat(INDENT3 "HaveWheel: %s\n",
+            toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
+}
+
+void RotaryEncoderInputMapper::configure(nsecs_t when,
+        const InputReaderConfiguration* config, uint32_t changes) {
+    InputMapper::configure(when, config, changes);
+    if (!changes) {
+        mRotaryEncoderScrollAccumulator.configure(getDevice());
+    }
+}
+
+void RotaryEncoderInputMapper::reset(nsecs_t when) {
+    mRotaryEncoderScrollAccumulator.reset(getDevice());
+
+    InputMapper::reset(when);
+}
+
+void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
+    mRotaryEncoderScrollAccumulator.process(rawEvent);
+
+    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
+        sync(rawEvent->when);
+    }
+}
+
+void RotaryEncoderInputMapper::sync(nsecs_t when) {
+    PointerCoords pointerCoords;
+    pointerCoords.clear();
+
+    PointerProperties pointerProperties;
+    pointerProperties.clear();
+    pointerProperties.id = 0;
+    pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
+
+    float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
+    bool scrolled = scroll != 0;
+
+    // This is not a pointer, so it's not associated with a display.
+    int32_t displayId = ADISPLAY_ID_NONE;
+
+    // Moving the rotary encoder should wake the device (if specified).
+    uint32_t policyFlags = 0;
+    if (scrolled && getDevice()->isExternal()) {
+        policyFlags |= POLICY_FLAG_WAKE;
+    }
+
+    // Send motion event.
+    if (scrolled) {
+        int32_t metaState = mContext->getGlobalMetaState();
+        pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
+
+        NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
+                AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
+                AMOTION_EVENT_EDGE_FLAG_NONE,
+                displayId, 1, &pointerProperties, &pointerCoords,
+                0, 0, 0);
+        getListener()->notifyMotion(&scrollArgs);
+    }
+
+    mRotaryEncoderScrollAccumulator.finishSync();
+}
 
 // --- TouchInputMapper ---
 
@@ -2962,15 +3099,15 @@
     // multitouch.  The spot-based presentation relies on being able to accurately
     // locate two or more fingers on the touch pad.
     mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
-            ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
+            ? Parameters::GESTURE_MODE_SINGLE_TOUCH : Parameters::GESTURE_MODE_MULTI_TOUCH;
 
     String8 gestureModeString;
     if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
             gestureModeString)) {
-        if (gestureModeString == "pointer") {
-            mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
-        } else if (gestureModeString == "spots") {
-            mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
+        if (gestureModeString == "single-touch") {
+            mParameters.gestureMode = Parameters::GESTURE_MODE_SINGLE_TOUCH;
+        } else if (gestureModeString == "multi-touch") {
+            mParameters.gestureMode = Parameters::GESTURE_MODE_MULTI_TOUCH;
         } else if (gestureModeString != "default") {
             ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
         }
@@ -3038,11 +3175,11 @@
     dump.append(INDENT3 "Parameters:\n");
 
     switch (mParameters.gestureMode) {
-    case Parameters::GESTURE_MODE_POINTER:
-        dump.append(INDENT4 "GestureMode: pointer\n");
+    case Parameters::GESTURE_MODE_SINGLE_TOUCH:
+        dump.append(INDENT4 "GestureMode: single-touch\n");
         break;
-    case Parameters::GESTURE_MODE_SPOTS:
-        dump.append(INDENT4 "GestureMode: spots\n");
+    case Parameters::GESTURE_MODE_MULTI_TOUCH:
+        dump.append(INDENT4 "GestureMode: multi-touch\n");
         break;
     default:
         assert(false);
@@ -4838,14 +4975,17 @@
     }
 
     // Update the pointer presentation and spots.
-    if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
-        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
+    if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
+        mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
         if (finishPreviousGesture || cancelPreviousGesture) {
             mPointerController->clearSpots();
         }
-        mPointerController->setSpots(mPointerGesture.currentGestureCoords,
-                mPointerGesture.currentGestureIdToIndex,
-                mPointerGesture.currentGestureIdBits);
+
+        if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
+            mPointerController->setSpots(mPointerGesture.currentGestureCoords,
+                     mPointerGesture.currentGestureIdToIndex,
+                     mPointerGesture.currentGestureIdBits);
+        }
     } else {
         mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
     }
@@ -4854,9 +4994,8 @@
     switch (mPointerGesture.currentGestureMode) {
     case PointerGesture::NEUTRAL:
     case PointerGesture::QUIET:
-        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
-                && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
-                        || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
+        if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH
+                && mPointerGesture.lastGestureMode == PointerGesture::FREEFORM) {
             // Remind the user of where the pointer is after finishing a gesture with spots.
             mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
         }
@@ -4866,15 +5005,15 @@
     case PointerGesture::BUTTON_CLICK_OR_DRAG:
     case PointerGesture::HOVER:
     case PointerGesture::PRESS:
+    case PointerGesture::SWIPE:
         // Unfade the pointer when the current gesture manipulates the
         // area directly under the pointer.
         mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
         break;
-    case PointerGesture::SWIPE:
     case PointerGesture::FREEFORM:
         // Fade the pointer when the current gesture manipulates a different
         // area and there are spots to guide the user experience.
-        if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
+        if (mParameters.gestureMode == Parameters::GESTURE_MODE_MULTI_TOUCH) {
             mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
         } else {
             mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
@@ -5240,13 +5379,14 @@
             }
         }
 
+        float deltaX = 0, deltaY = 0;
         if (activeTouchId >= 0 && mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
             const RawPointerData::Pointer& currentPointer =
                     mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
             const RawPointerData::Pointer& lastPointer =
                     mLastRawState.rawPointerData.pointerForId(activeTouchId);
-            float deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
-            float deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
+            deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+            deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
 
             rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
             mPointerVelocityControl.move(when, &deltaX, &deltaY);
@@ -5273,6 +5413,8 @@
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
     } else if (currentFingerCount == 0) {
         // Case 3. No fingers down and button is not pressed. (NEUTRAL)
         if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
@@ -5380,15 +5522,14 @@
             mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
         }
 
+        float deltaX = 0, deltaY = 0;
         if (mLastCookedState.fingerIdBits.hasBit(activeTouchId)) {
             const RawPointerData::Pointer& currentPointer =
                     mCurrentRawState.rawPointerData.pointerForId(activeTouchId);
             const RawPointerData::Pointer& lastPointer =
                     mLastRawState.rawPointerData.pointerForId(activeTouchId);
-            float deltaX = (currentPointer.x - lastPointer.x)
-                    * mPointerXMovementScale;
-            float deltaY = (currentPointer.y - lastPointer.y)
-                    * mPointerYMovementScale;
+            deltaX = (currentPointer.x - lastPointer.x) * mPointerXMovementScale;
+            deltaY = (currentPointer.y - lastPointer.y) * mPointerYMovementScale;
 
             rotateDelta(mSurfaceOrientation, &deltaX, &deltaY);
             mPointerVelocityControl.move(when, &deltaX, &deltaY);
@@ -5432,6 +5573,10 @@
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
                 down ? 1.0f : 0.0f);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(
+                AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+        mPointerGesture.currentGestureCoords[0].setAxisValue(
+                AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
 
         if (lastFingerCount == 0 && currentFingerCount != 0) {
             mPointerGesture.resetTap();
@@ -5678,6 +5823,10 @@
                     mPointerGesture.referenceGestureX);
             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
                     mPointerGesture.referenceGestureY);
+            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X,
+                    commonDeltaX);
+            mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y,
+                    commonDeltaY);
             mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
         } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
             // FREEFORM mode.
@@ -5774,6 +5923,10 @@
                         AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
                 mPointerGesture.currentGestureCoords[i].setAxisValue(
                         AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
+                mPointerGesture.currentGestureCoords[i].setAxisValue(
+                        AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
+                mPointerGesture.currentGestureCoords[i].setAxisValue(
+                        AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
             }
 
             if (mPointerGesture.activeGestureId < 0) {
@@ -5867,12 +6020,13 @@
     if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
         uint32_t id = mCurrentCookedState.mouseIdBits.firstMarkedBit();
         uint32_t currentIndex = mCurrentRawState.rawPointerData.idToIndex[id];
+        float deltaX = 0, deltaY = 0;
         if (mLastCookedState.mouseIdBits.hasBit(id)) {
             uint32_t lastIndex = mCurrentRawState.rawPointerData.idToIndex[id];
-            float deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
+            deltaX = (mCurrentRawState.rawPointerData.pointers[currentIndex].x
                     - mLastRawState.rawPointerData.pointers[lastIndex].x)
                     * mPointerXMovementScale;
-            float deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
+            deltaY = (mCurrentRawState.rawPointerData.pointers[currentIndex].y
                     - mLastRawState.rawPointerData.pointers[lastIndex].y)
                     * mPointerYMovementScale;
 
@@ -5895,6 +6049,8 @@
         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
         mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
                 hovering ? 0.0f : 1.0f);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, x);
+        mPointerSimple.currentCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, y);
         mPointerSimple.currentProperties.id = 0;
         mPointerSimple.currentProperties.toolType =
                 mCurrentCookedState.cookedPointerData.pointerProperties[currentIndex].toolType;
diff --git a/services/inputflinger/InputReader.h b/services/inputflinger/InputReader.h
index 30c84b1..076f3d6 100644
--- a/services/inputflinger/InputReader.h
+++ b/services/inputflinger/InputReader.h
@@ -359,6 +359,9 @@
     virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
             int32_t sw) = 0;
 
+    /* Toggle Caps Lock */
+    virtual void toggleCapsLockState(int32_t deviceId) = 0;
+
     /* Determine whether physical keys exist for the given framework-domain key codes. */
     virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
             size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
@@ -461,6 +464,8 @@
     virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
             int32_t sw);
 
+    virtual void toggleCapsLockState(int32_t deviceId);
+
     virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
             size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
 
@@ -616,6 +621,7 @@
     void cancelTouch(nsecs_t when);
 
     int32_t getMetaState();
+    void updateMetaState(int32_t keyCode);
 
     void fadePointer();
 
@@ -1031,6 +1037,7 @@
     virtual void cancelTouch(nsecs_t when);
 
     virtual int32_t getMetaState();
+    virtual void updateMetaState(int32_t keyCode);
 
     virtual void updateExternalStylusState(const StylusState& state);
 
@@ -1116,6 +1123,7 @@
             const int32_t* keyCodes, uint8_t* outFlags);
 
     virtual int32_t getMetaState();
+    virtual void updateMetaState(int32_t keyCode);
 
 private:
     struct KeyDown {
@@ -1156,6 +1164,8 @@
 
     void processKey(nsecs_t when, bool down, int32_t scanCode, int32_t usageCode);
 
+    bool updateMetaStateIfNeeded(int32_t keyCode, bool down);
+
     ssize_t findKeyDown(int32_t scanCode);
 
     void resetLedState();
@@ -1231,6 +1241,27 @@
 };
 
 
+class RotaryEncoderInputMapper : public InputMapper {
+public:
+    RotaryEncoderInputMapper(InputDevice* device);
+    virtual ~RotaryEncoderInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void dump(String8& dump);
+    virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
+    virtual void reset(nsecs_t when);
+    virtual void process(const RawEvent* rawEvent);
+
+private:
+    CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
+
+    int32_t mSource;
+    float mScalingFactor;
+
+    void sync(nsecs_t when);
+};
+
 class TouchInputMapper : public InputMapper {
 public:
     TouchInputMapper(InputDevice* device);
@@ -1305,8 +1336,8 @@
         bool hasButtonUnderPad;
 
         enum GestureMode {
-            GESTURE_MODE_POINTER,
-            GESTURE_MODE_SPOTS,
+            GESTURE_MODE_SINGLE_TOUCH,
+            GESTURE_MODE_MULTI_TOUCH,
         };
         GestureMode gestureMode;
 
diff --git a/services/inputflinger/host/Android.mk b/services/inputflinger/host/Android.mk
index b828175..0a7fc27 100644
--- a/services/inputflinger/host/Android.mk
+++ b/services/inputflinger/host/Android.mk
@@ -58,5 +58,6 @@
 	libutils
 
 LOCAL_MODULE := inputflinger
+LOCAL_INIT_RC := inputflinger.rc
 
 include $(BUILD_EXECUTABLE)
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 630a596..bd11d56 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -14,8 +14,11 @@
  * limitations under the License.
  */
 
+#include <functional>
 #include <stdint.h>
 #include <sys/types.h>
+#include <unordered_map>
+#include <vector>
 
 #define LOG_TAG "InputDriver"
 
@@ -25,11 +28,64 @@
 #include "InputHost.h"
 
 #include <hardware/input.h>
+#include <input/InputDevice.h>
 #include <utils/Log.h>
+#include <utils/PropertyMap.h>
 #include <utils/String8.h>
 
 #define INDENT2 "    "
 
+struct input_property_map {
+    android::PropertyMap* propertyMap;
+};
+
+struct input_property {
+    android::String8 key;
+    android::String8 value;
+};
+
+struct input_device_identifier {
+    const char* name;
+    const char* uniqueId;
+    input_bus_t bus;
+    int32_t     vendorId;
+    int32_t     productId;
+    int32_t     version;
+};
+
+struct input_device_definition {
+    std::vector<input_report_definition*> reportDefs;
+};
+
+struct input_device_handle {
+    input_device_identifier_t* id;
+    input_device_definition_t* def;
+};
+
+struct input_int_usage {
+    input_usage_t usage;
+    int32_t min;
+    int32_t max;
+    float   resolution;
+};
+
+struct input_collection {
+    int32_t arity;
+    std::vector<input_int_usage> intUsages;
+    std::vector<input_usage_t> boolUsages;
+};
+
+struct InputCollectionIdHasher {
+    std::size_t operator()(const input_collection_id& id) const {
+        return std::hash<int>()(static_cast<int>(id));
+    }
+};
+
+struct input_report_definition {
+    std::unordered_map<input_collection_id_t, input_collection, InputCollectionIdHasher> collections;
+};
+
+
 namespace android {
 
 static input_host_callbacks_t kCallbacks = {
@@ -37,6 +93,7 @@
     .create_device_definition = create_device_definition,
     .create_input_report_definition = create_input_report_definition,
     .create_output_report_definition = create_output_report_definition,
+    .free_report_definition = free_report_definition,
     .input_device_definition_add_report = input_device_definition_add_report,
     .input_report_definition_add_collection = input_report_definition_add_collection,
     .input_report_definition_declare_usage_int = input_report_definition_declare_usage_int,
@@ -61,86 +118,295 @@
     mHal = reinterpret_cast<const input_module_t*>(module);
 }
 
-void InputDriver::init(InputHostInterface* host) {
-    mHal->init(mHal, static_cast<input_host_t*>(host), kCallbacks);
+void InputDriver::init() {
+    mHal->init(mHal, static_cast<input_host_t*>(this), kCallbacks);
+}
+
+input_device_identifier_t* InputDriver::createDeviceIdentifier(
+            const char* name, int32_t productId, int32_t vendorId,
+            input_bus_t bus, const char* uniqueId) {
+    auto identifier = new ::input_device_identifier {
+        .name = name,
+        .productId = productId,
+        .vendorId = vendorId,
+        .bus = bus,
+        .uniqueId = uniqueId,
+    };
+    // TODO: store this identifier somewhere
+    return identifier;
+}
+
+input_device_definition_t* InputDriver::createDeviceDefinition() {
+    return new ::input_device_definition;
+}
+
+input_report_definition_t* InputDriver::createInputReportDefinition() {
+    return new ::input_report_definition;
+}
+
+input_report_definition_t* InputDriver::createOutputReportDefinition() {
+    return new ::input_report_definition;
+}
+
+void InputDriver::freeReportDefinition(input_report_definition_t* reportDef) {
+    delete reportDef;
+}
+
+void InputDriver::inputDeviceDefinitionAddReport(input_device_definition_t* d,
+        input_report_definition_t* r) {
+    d->reportDefs.push_back(r);
+}
+
+void InputDriver::inputReportDefinitionAddCollection(input_report_definition_t* report,
+        input_collection_id_t id, int32_t arity) {
+    report->collections[id] = {.arity = arity};
+}
+
+void InputDriver::inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+        input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+        float resolution) {
+    if (report->collections.find(id) != report->collections.end()) {
+        report->collections[id].intUsages.push_back({
+                .usage = usage, .min = min, .max = max, .resolution = resolution});
+    }
+}
+
+void InputDriver::inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+        input_collection_id_t id, input_usage_t* usage, size_t usageCount) {
+    if (report->collections.find(id) != report->collections.end()) {
+        for (size_t i = 0; i < usageCount; ++i) {
+            report->collections[id].boolUsages.push_back(usage[i]);
+        }
+    }
+}
+
+input_device_handle_t* InputDriver::registerDevice(input_device_identifier_t* id,
+        input_device_definition_t* d) {
+    ALOGD("Registering device %s with %zu input reports", id->name, d->reportDefs.size());
+    // TODO: save this device handle
+    return new input_device_handle{ .id = id, .def = d };
+}
+
+void InputDriver::unregisterDevice(input_device_handle_t* handle) {
+    delete handle;
+}
+
+input_report_t* InputDriver::inputAllocateReport(input_report_definition_t* r) {
+    ALOGD("Allocating input report for definition %p", r);
+    return nullptr;
+}
+
+void InputDriver::inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+        input_usage_t usage, int32_t value, int32_t arity_index) {
+}
+
+void InputDriver::inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+        input_usage_t usage, bool value, int32_t arity_index) {
+}
+
+void InputDriver::reportEvent(input_device_handle_t* d, input_report_t* report) {
+    ALOGD("report_event %p for handle %p", report, d);
+}
+
+input_property_map_t* InputDriver::inputGetDevicePropertyMap(input_device_identifier_t* id) {
+    InputDeviceIdentifier idi;
+    idi.name = id->name;
+    idi.uniqueId = id->uniqueId;
+    idi.bus = id->bus;
+    idi.vendor = id->vendorId;
+    idi.product = id->productId;
+    idi.version = id->version;
+
+    String8 configFile = getInputDeviceConfigurationFilePathByDeviceIdentifier(
+            idi, INPUT_DEVICE_CONFIGURATION_FILE_TYPE_CONFIGURATION);
+    if (configFile.isEmpty()) {
+        ALOGD("No input device configuration file found for device '%s'.",
+                idi.name.string());
+    } else {
+        auto propMap = new input_property_map_t();
+        status_t status = PropertyMap::load(configFile, &propMap->propertyMap);
+        if (status) {
+            ALOGE("Error loading input device configuration file for device '%s'. "
+                    "Using default configuration.",
+                    idi.name.string());
+            delete propMap;
+            return nullptr;
+        }
+        return propMap;
+    }
+    return nullptr;
+}
+
+input_property_t* InputDriver::inputGetDeviceProperty(input_property_map_t* map,
+        const char* key) {
+    String8 keyString(key);
+    if (map != nullptr) {
+        if (map->propertyMap->hasProperty(keyString)) {
+            auto prop = new input_property_t();
+            if (!map->propertyMap->tryGetProperty(keyString, prop->value)) {
+                delete prop;
+                return nullptr;
+            }
+            prop->key = keyString;
+            return prop;
+        }
+    }
+    return nullptr;
+}
+
+const char* InputDriver::inputGetPropertyKey(input_property_t* property) {
+    if (property != nullptr) {
+        return property->key.string();
+    }
+    return nullptr;
+}
+
+const char* InputDriver::inputGetPropertyValue(input_property_t* property) {
+    if (property != nullptr) {
+        return property->value.string();
+    }
+    return nullptr;
+}
+
+void InputDriver::inputFreeDeviceProperty(input_property_t* property) {
+    if (property != nullptr) {
+        delete property;
+    }
+}
+
+void InputDriver::inputFreeDevicePropertyMap(input_property_map_t* map) {
+    if (map != nullptr) {
+        delete map->propertyMap;
+        delete map;
+    }
 }
 
 void InputDriver::dump(String8& result) {
     result.appendFormat(INDENT2 "HAL Input Driver (%s)\n", mName.string());
 }
 
+} // namespace android
 
 // HAL wrapper functions
 
-input_device_identifier_t* create_device_identifier(input_host_t* host,
+namespace android {
+
+::input_device_identifier_t* create_device_identifier(input_host_t* host,
         const char* name, int32_t product_id, int32_t vendor_id,
         input_bus_t bus, const char* unique_id) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createDeviceIdentifier(name, product_id, vendor_id, bus, unique_id);
 }
 
 input_device_definition_t* create_device_definition(input_host_t* host) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createDeviceDefinition();
 }
 
 input_report_definition_t* create_input_report_definition(input_host_t* host) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createInputReportDefinition();
 }
 
 input_report_definition_t* create_output_report_definition(input_host_t* host) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->createOutputReportDefinition();
+}
+
+void free_report_definition(input_host_t* host, input_report_definition_t* report_def) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->freeReportDefinition(report_def);
 }
 
 void input_device_definition_add_report(input_host_t* host,
-        input_device_definition_t* d, input_report_definition_t* r) { }
+        input_device_definition_t* d, input_report_definition_t* r) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputDeviceDefinitionAddReport(d, r);
+}
 
 void input_report_definition_add_collection(input_host_t* host,
-        input_report_definition_t* report, input_collection_id_t id, int32_t arity) { }
+        input_report_definition_t* report, input_collection_id_t id, int32_t arity) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportDefinitionAddCollection(report, id, arity);
+}
 
 void input_report_definition_declare_usage_int(input_host_t* host,
         input_report_definition_t* report, input_collection_id_t id,
-        input_usage_t usage, int32_t min, int32_t max, float resolution) { }
+        input_usage_t usage, int32_t min, int32_t max, float resolution) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportDefinitionDeclareUsageInt(report, id, usage, min, max, resolution);
+}
 
 void input_report_definition_declare_usages_bool(input_host_t* host,
         input_report_definition_t* report, input_collection_id_t id,
-        input_usage_t* usage, size_t usage_count) { }
-
+        input_usage_t* usage, size_t usage_count) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportDefinitionDeclareUsagesBool(report, id, usage, usage_count);
+}
 
 input_device_handle_t* register_device(input_host_t* host,
         input_device_identifier_t* id, input_device_definition_t* d) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->registerDevice(id, d);
+}
+
+void unregister_device(input_host_t* host, input_device_handle_t* handle) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->unregisterDevice(handle);
 }
 
 input_report_t* input_allocate_report(input_host_t* host, input_report_definition_t* r) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputAllocateReport(r);
 }
+
 void input_report_set_usage_int(input_host_t* host, input_report_t* r,
-        input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) { }
+        input_collection_id_t id, input_usage_t usage, int32_t value, int32_t arity_index) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportSetUsageInt(r, id, usage, value, arity_index);
+}
 
 void input_report_set_usage_bool(input_host_t* host, input_report_t* r,
-        input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) { }
+        input_collection_id_t id, input_usage_t usage, bool value, int32_t arity_index) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputReportSetUsageBool(r, id, usage, value, arity_index);
+}
 
-void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) { }
+void report_event(input_host_t* host, input_device_handle_t* d, input_report_t* report) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->reportEvent(d, report);
+}
 
 input_property_map_t* input_get_device_property_map(input_host_t* host,
         input_device_identifier_t* id) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetDevicePropertyMap(id);
 }
 
 input_property_t* input_get_device_property(input_host_t* host, input_property_map_t* map,
         const char* key) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetDeviceProperty(map, key);
 }
 
 const char* input_get_property_key(input_host_t* host, input_property_t* property) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetPropertyKey(property);
 }
 
 const char* input_get_property_value(input_host_t* host, input_property_t* property) {
-    return nullptr;
+    auto driver = static_cast<InputDriverInterface*>(host);
+    return driver->inputGetPropertyValue(property);
 }
 
-void input_free_device_property(input_host_t* host, input_property_t* property) { }
+void input_free_device_property(input_host_t* host, input_property_t* property) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputFreeDeviceProperty(property);
+}
 
-void input_free_device_property_map(input_host_t* host, input_property_map_t* map) { }
+void input_free_device_property_map(input_host_t* host, input_property_map_t* map) {
+    auto driver = static_cast<InputDriverInterface*>(host);
+    driver->inputFreeDevicePropertyMap(map);
+}
 
 } // namespace android
diff --git a/services/inputflinger/host/InputDriver.h b/services/inputflinger/host/InputDriver.h
index 7734ac2..8d5a31e 100644
--- a/services/inputflinger/host/InputDriver.h
+++ b/services/inputflinger/host/InputDriver.h
@@ -26,17 +26,56 @@
 #include <utils/RefBase.h>
 #include <utils/String8.h>
 
+// Declare a concrete type for the HAL
+struct input_host {
+};
+
 namespace android {
 
-class InputHostInterface;
-
-class InputDriverInterface : public virtual RefBase {
+class InputDriverInterface : public input_host_t, public virtual RefBase {
 protected:
     InputDriverInterface() = default;
     virtual ~InputDriverInterface() = default;
 
 public:
-    virtual void init(InputHostInterface* host) = 0;
+    virtual void init() = 0;
+
+    virtual input_device_identifier_t* createDeviceIdentifier(
+            const char* name, int32_t productId, int32_t vendorId,
+            input_bus_t bus, const char* uniqueId) = 0;
+    virtual input_device_definition_t* createDeviceDefinition() = 0;
+    virtual input_report_definition_t* createInputReportDefinition() = 0;
+    virtual input_report_definition_t* createOutputReportDefinition() = 0;
+    virtual void freeReportDefinition(input_report_definition_t* reportDef) = 0;
+
+    virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
+            input_report_definition_t* r) = 0;
+    virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
+            input_collection_id_t id, int32_t arity) = 0;
+    virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+            float resolution) = 0;
+    virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t* usage, size_t usageCount) = 0;
+
+    virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
+            input_device_definition_t* d) = 0;
+    virtual void unregisterDevice(input_device_handle_t* handle) = 0;
+
+    virtual input_report_t* inputAllocateReport(input_report_definition_t* r) = 0;
+    virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, int32_t value, int32_t arity_index) = 0;
+    virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, bool value, int32_t arity_index) = 0;
+    virtual void reportEvent(input_device_handle_t* d, input_report_t* report) = 0;
+
+    virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) = 0;
+    virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
+            const char* key) = 0;
+    virtual const char* inputGetPropertyKey(input_property_t* property) = 0;
+    virtual const char* inputGetPropertyValue(input_property_t* property) = 0;
+    virtual void inputFreeDeviceProperty(input_property_t* property) = 0;
+    virtual void inputFreeDevicePropertyMap(input_property_map_t* map) = 0;
 
     virtual void dump(String8& result) = 0;
 };
@@ -46,7 +85,44 @@
     InputDriver(const char* name);
     virtual ~InputDriver() = default;
 
-    virtual void init(InputHostInterface* host) override;
+    virtual void init() override;
+
+    virtual input_device_identifier_t* createDeviceIdentifier(
+            const char* name, int32_t productId, int32_t vendorId,
+            input_bus_t bus, const char* uniqueId) override;
+    virtual input_device_definition_t* createDeviceDefinition() override;
+    virtual input_report_definition_t* createInputReportDefinition() override;
+    virtual input_report_definition_t* createOutputReportDefinition() override;
+    virtual void freeReportDefinition(input_report_definition_t* reportDef) override;
+
+    virtual void inputDeviceDefinitionAddReport(input_device_definition_t* d,
+            input_report_definition_t* r) override;
+    virtual void inputReportDefinitionAddCollection(input_report_definition_t* report,
+            input_collection_id_t id, int32_t arity) override;
+    virtual void inputReportDefinitionDeclareUsageInt(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t usage, int32_t min, int32_t max,
+            float resolution) override;
+    virtual void inputReportDefinitionDeclareUsagesBool(input_report_definition_t* report,
+            input_collection_id_t id, input_usage_t* usage, size_t usageCount) override;
+
+    virtual input_device_handle_t* registerDevice(input_device_identifier_t* id,
+            input_device_definition_t* d) override;
+    virtual void unregisterDevice(input_device_handle_t* handle) override;
+
+    virtual input_report_t* inputAllocateReport(input_report_definition_t* r) override;
+    virtual void inputReportSetUsageInt(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, int32_t value, int32_t arity_index) override;
+    virtual void inputReportSetUsageBool(input_report_t* r, input_collection_id_t id,
+            input_usage_t usage, bool value, int32_t arity_index) override;
+    virtual void reportEvent(input_device_handle_t* d, input_report_t* report) override;
+
+    virtual input_property_map_t* inputGetDevicePropertyMap(input_device_identifier_t* id) override;
+    virtual input_property_t* inputGetDeviceProperty(input_property_map_t* map,
+            const char* key) override;
+    virtual const char* inputGetPropertyKey(input_property_t* property) override;
+    virtual const char* inputGetPropertyValue(input_property_t* property) override;
+    virtual void inputFreeDeviceProperty(input_property_t* property) override;
+    virtual void inputFreeDevicePropertyMap(input_property_map_t* map) override;
 
     virtual void dump(String8& result) override;
 
@@ -68,6 +144,8 @@
 
 input_report_definition_t* create_output_report_definition(input_host_t* host);
 
+void free_report_definition(input_host_t* host, input_report_definition_t* report_def);
+
 void input_device_definition_add_report(input_host_t* host,
         input_device_definition_t* d, input_report_definition_t* r);
 
diff --git a/services/inputflinger/host/InputHost.cpp b/services/inputflinger/host/InputHost.cpp
index 51d3e6b..094200a 100644
--- a/services/inputflinger/host/InputHost.cpp
+++ b/services/inputflinger/host/InputHost.cpp
@@ -28,7 +28,7 @@
 
 void InputHost::registerInputDriver(InputDriverInterface* driver) {
     LOG_ALWAYS_FATAL_IF(driver == nullptr, "Cannot register a nullptr as an InputDriver!");
-    driver->init(this);
+    driver->init();
     mDrivers.push_back(driver);
 }
 
diff --git a/services/inputflinger/host/InputHost.h b/services/inputflinger/host/InputHost.h
index 42a66e0..eda4a89 100644
--- a/services/inputflinger/host/InputHost.h
+++ b/services/inputflinger/host/InputHost.h
@@ -26,15 +26,11 @@
 
 #include "InputDriver.h"
 
-// Declare a concrete type for the HAL
-struct input_host {
-};
-
 namespace android {
 
 class InputDriverInterface;
 
-class InputHostInterface : public input_host_t, public virtual RefBase {
+class InputHostInterface : public virtual RefBase {
 protected:
     InputHostInterface() = default;
     virtual ~InputHostInterface() = default;
diff --git a/services/inputflinger/host/inputflinger.rc b/services/inputflinger/host/inputflinger.rc
new file mode 100644
index 0000000..4130ddc
--- /dev/null
+++ b/services/inputflinger/host/inputflinger.rc
@@ -0,0 +1,5 @@
+service inputflinger /system/bin/inputflinger
+    class main
+    user system
+    group input wakelock
+#    onrestart restart zygote
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 2d8eaef..7ae36d8 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -170,7 +170,7 @@
             << "Should reject motion events with pointer down index too large.";
 
     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            AMOTION_EVENT_ACTION_POINTER_DOWN | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
             ARBITRARY_TIME, ARBITRARY_TIME,
             /*pointerCount*/ 1, pointerProperties, pointerCoords);
@@ -191,7 +191,7 @@
             << "Should reject motion events with pointer up index too large.";
 
     event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
-            AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+            AMOTION_EVENT_ACTION_POINTER_UP | (~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
             0, 0, 0, AMETA_NONE, 0, 0, 0, 0, 0,
             ARBITRARY_TIME, ARBITRARY_TIME,
             /*pointerCount*/ 1, pointerProperties, pointerCoords);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 42bc865..a7fe69c 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1528,8 +1528,8 @@
     NotifySwitchArgs args;
     ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySwitchWasCalled(&args));
     ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
-    ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT), args.switchValues);
-    ASSERT_EQ((1 << SW_LID) | (1 << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
+    ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT), args.switchValues);
+    ASSERT_EQ((1U << SW_LID) | (1U << SW_JACK_PHYSICAL_INSERT) | (1 << SW_HEADPHONE_INSERT),
             args.switchMask);
     ASSERT_EQ(uint32_t(0), args.policyFlags);
 }
diff --git a/services/powermanager/Android.mk b/services/powermanager/Android.mk
index 7b24c65..4deb115 100644
--- a/services/powermanager/Android.mk
+++ b/services/powermanager/Android.mk
@@ -14,4 +14,6 @@
 
 LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
 
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/../../include
+
 include $(BUILD_SHARED_LIBRARY)
diff --git a/services/powermanager/IPowerManager.cpp b/services/powermanager/IPowerManager.cpp
index ec864ee..bff8719 100644
--- a/services/powermanager/IPowerManager.cpp
+++ b/services/powermanager/IPowerManager.cpp
@@ -27,15 +27,6 @@
 
 namespace android {
 
-// must be kept in sync with IPowerManager.aidl
-enum {
-    ACQUIRE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION,
-    ACQUIRE_WAKE_LOCK_UID = IBinder::FIRST_CALL_TRANSACTION + 1,
-    RELEASE_WAKE_LOCK = IBinder::FIRST_CALL_TRANSACTION + 2,
-    UPDATE_WAKE_LOCK_UIDS = IBinder::FIRST_CALL_TRANSACTION + 3,
-    POWER_HINT = IBinder::FIRST_CALL_TRANSACTION + 4,
-};
-
 class BpPowerManager : public BpInterface<IPowerManager>
 {
 public:
@@ -104,6 +95,44 @@
         // This FLAG_ONEWAY is in the .aidl, so there is no way to disable it
         return remote()->transact(POWER_HINT, data, &reply, IBinder::FLAG_ONEWAY);
     }
+
+    virtual status_t goToSleep(int64_t event_time_ms, int reason, int flags)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeInt64(event_time_ms);
+        data.writeInt32(reason);
+        data.writeInt32(flags);
+        return remote()->transact(GO_TO_SLEEP, data, &reply, 0);
+    }
+
+    virtual status_t reboot(bool confirm, const String16& reason, bool wait)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeInt32(confirm);
+        data.writeString16(reason);
+        data.writeInt32(wait);
+        return remote()->transact(REBOOT, data, &reply, 0);
+    }
+
+    virtual status_t shutdown(bool confirm, const String16& reason, bool wait)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeInt32(confirm);
+        data.writeString16(reason);
+        data.writeInt32(wait);
+        return remote()->transact(SHUTDOWN, data, &reply, 0);
+    }
+
+    virtual status_t crash(const String16& message)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPowerManager::getInterfaceDescriptor());
+        data.writeString16(message);
+        return remote()->transact(CRASH, data, &reply, 0);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(PowerManager, "android.os.IPowerManager");
diff --git a/services/sensorservice/Android.mk b/services/sensorservice/Android.mk
index 4f24ddc..5a36961 100644
--- a/services/sensorservice/Android.mk
+++ b/services/sensorservice/Android.mk
@@ -2,31 +2,39 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	BatteryService.cpp \
-	CorrectedGyroSensor.cpp \
+    BatteryService.cpp \
+    CorrectedGyroSensor.cpp \
     Fusion.cpp \
     GravitySensor.cpp \
     LinearAccelerationSensor.cpp \
     OrientationSensor.cpp \
+    RecentEventLogger.cpp \
     RotationVectorSensor.cpp \
     SensorDevice.cpp \
+    SensorEventConnection.cpp \
     SensorFusion.cpp \
     SensorInterface.cpp \
-    SensorService.cpp
+    SensorList.cpp \
+    SensorRecord.cpp \
+    SensorService.cpp \
+    SensorServiceUtils.cpp \
+
 
 LOCAL_CFLAGS:= -DLOG_TAG=\"SensorService\"
 
+LOCAL_CFLAGS += -Wall -Werror -Wextra
+
 LOCAL_CFLAGS += -fvisibility=hidden
 
 LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libhardware \
-	libhardware_legacy \
-	libutils \
-	liblog \
-	libbinder \
-	libui \
-	libgui
+    libcutils \
+    libhardware \
+    libhardware_legacy \
+    libutils \
+    liblog \
+    libbinder \
+    libui \
+    libgui
 
 LOCAL_MODULE:= libsensorservice
 
@@ -37,12 +45,14 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:= \
-	main_sensorservice.cpp
+    main_sensorservice.cpp
 
 LOCAL_SHARED_LIBRARIES := \
-	libsensorservice \
-	libbinder \
-	libutils
+    libsensorservice \
+    libbinder \
+    libutils
+
+LOCAL_CFLAGS := -Wall -Werror -Wextra
 
 LOCAL_MODULE_TAGS := optional
 
diff --git a/services/sensorservice/BatteryService.cpp b/services/sensorservice/BatteryService.cpp
index cb962a6..81f32cd 100644
--- a/services/sensorservice/BatteryService.cpp
+++ b/services/sensorservice/BatteryService.cpp
@@ -83,7 +83,7 @@
     if (mBatteryStatService != 0) {
         Mutex::Autolock _l(mActivationsLock);
         int64_t identity = IPCThreadState::self()->clearCallingIdentity();
-        for (ssize_t i=0 ; i<mActivations.size() ; i++) {
+        for (size_t i=0 ; i<mActivations.size() ; i++) {
             const Info& info(mActivations[i]);
             if (info.uid == uid) {
                 mBatteryStatService->noteStopSensor(info.uid, info.handle);
diff --git a/services/sensorservice/CorrectedGyroSensor.cpp b/services/sensorservice/CorrectedGyroSensor.cpp
index b07d544..005af18 100644
--- a/services/sensorservice/CorrectedGyroSensor.cpp
+++ b/services/sensorservice/CorrectedGyroSensor.cpp
@@ -30,15 +30,26 @@
 // ---------------------------------------------------------------------------
 
 CorrectedGyroSensor::CorrectedGyroSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
+    : VirtualSensor() {
     for (size_t i=0 ; i<count ; i++) {
         if (list[i].type == SENSOR_TYPE_GYROSCOPE) {
             mGyro = Sensor(list + i);
             break;
         }
     }
+
+    const sensor_t sensor = {
+            .name       = "Corrected Gyroscope Sensor",
+            .vendor     = "AOSP",
+            .version    = 1,
+            .handle     = '_cgy',
+            .type       = SENSOR_TYPE_GYROSCOPE,
+            .maxRange   = mGyro.getMaxValue(),
+            .resolution = mGyro.getResolution(),
+            .power      = mSensorFusion.getPowerUsage(),
+            .minDelay   = mGyro.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool CorrectedGyroSensor::process(sensors_event_t* outEvent,
@@ -58,27 +69,12 @@
 
 status_t CorrectedGyroSensor::activate(void* ident, bool enabled) {
     mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
-    return mSensorFusion.activate(ident, enabled);
+    return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
 }
 
 status_t CorrectedGyroSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
     mSensorDevice.setDelay(ident, mGyro.getHandle(), ns);
-    return mSensorFusion.setDelay(ident, ns);
-}
-
-Sensor CorrectedGyroSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Corrected Gyroscope Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_cgy';
-    hwSensor.type       = SENSOR_TYPE_GYROSCOPE;
-    hwSensor.maxRange   = mGyro.getMaxValue();
-    hwSensor.resolution = mGyro.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mGyro.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
+    return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/CorrectedGyroSensor.h b/services/sensorservice/CorrectedGyroSensor.h
index 3c49c08..68acd43 100644
--- a/services/sensorservice/CorrectedGyroSensor.h
+++ b/services/sensorservice/CorrectedGyroSensor.h
@@ -31,19 +31,14 @@
 class SensorDevice;
 class SensorFusion;
 
-class CorrectedGyroSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
+class CorrectedGyroSensor : public VirtualSensor {
     Sensor mGyro;
 
 public:
     CorrectedGyroSensor(sensor_t const* list, size_t count);
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
+    virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+    virtual status_t activate(void* ident, bool enabled) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index 4f63c31..e92b23d 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -24,28 +24,44 @@
 
 // -----------------------------------------------------------------------
 
+/*==================== BEGIN FUSION SENSOR PARAMETER =========================*/
+
+/* Note:
+ *   If a platform uses software fusion, it is necessary to tune the following
+ *   parameters to fit the hardware sensors prior to release.
+ *
+ *   The DEFAULT_ parameters will be used in FUSION_9AXIS and FUSION_NOMAG mode.
+ *   The GEOMAG_ parameters will be used in FUSION_NOGYRO mode.
+ */
+
 /*
- * gyroVAR gives the measured variance of the gyro's output per
+ * GYRO_VAR gives the measured variance of the gyro's output per
  * Hz (or variance at 1 Hz). This is an "intrinsic" parameter of the gyro,
  * which is independent of the sampling frequency.
  *
  * The variance of gyro's output at a given sampling period can be
  * calculated as:
- *      variance(T) = gyroVAR / T
+ *      variance(T) = GYRO_VAR / T
  *
  * The variance of the INTEGRATED OUTPUT at a given sampling period can be
  * calculated as:
- *       variance_integrate_output(T) = gyroVAR * T
- *
+ *       variance_integrate_output(T) = GYRO_VAR * T
  */
-static const float gyroVAR = 1e-7;      // (rad/s)^2 / Hz
-static const float biasVAR = 1e-8;      // (rad/s)^2 / s (guessed)
+static const float DEFAULT_GYRO_VAR = 1e-7;      // (rad/s)^2 / Hz
+static const float DEFAULT_GYRO_BIAS_VAR = 1e-12;  // (rad/s)^2 / s (guessed)
+static const float GEOMAG_GYRO_VAR = 1e-4;      // (rad/s)^2 / Hz
+static const float GEOMAG_GYRO_BIAS_VAR = 1e-8;  // (rad/s)^2 / s (guessed)
 
 /*
  * Standard deviations of accelerometer and magnetometer
  */
-static const float accSTDEV  = 0.05f;   // m/s^2 (measured 0.08 / CDD 0.05)
-static const float magSTDEV  = 0.5f;    // uT    (measured 0.7  / CDD 0.5)
+static const float DEFAULT_ACC_STDEV  = 0.015f; // m/s^2 (measured 0.08 / CDD 0.05)
+static const float DEFAULT_MAG_STDEV  = 0.1f;   // uT    (measured 0.7  / CDD 0.5)
+static const float GEOMAG_ACC_STDEV  = 0.05f; // m/s^2 (measured 0.08 / CDD 0.05)
+static const float GEOMAG_MAG_STDEV  = 0.1f;   // uT    (measured 0.7  / CDD 0.5)
+
+
+/* ====================== END FUSION SENSOR PARAMETER ========================*/
 
 static const float SYMMETRY_TOLERANCE = 1e-10f;
 
@@ -54,9 +70,8 @@
  * ill-conditioning and div by zeros.
  * Threshhold: 10% of g, in m/s^2
  */
-static const float FREE_FALL_THRESHOLD = 0.981f;
-static const float FREE_FALL_THRESHOLD_SQ =
-        FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD;
+static const float NOMINAL_GRAVITY = 9.81f;
+static const float FREE_FALL_THRESHOLD = 0.1f * (NOMINAL_GRAVITY);
 
 /*
  * The geomagnetic-field should be between 30uT and 60uT.
@@ -87,6 +102,8 @@
 static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ =
     MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG;
 
+static const float SQRT_3 = 1.732f;
+static const float WVEC_EPS = 1e-4f/SQRT_3;
 // -----------------------------------------------------------------------
 
 template <typename TYPE, size_t C, size_t R>
@@ -173,7 +190,7 @@
     init();
 }
 
-void Fusion::init() {
+void Fusion::init(int mode) {
     mInitState = 0;
 
     mGyroRate = 0;
@@ -183,6 +200,19 @@
     mCount[2] = 0;
 
     mData = 0;
+    mMode = mode;
+
+    if (mMode != FUSION_NOGYRO) { //normal or game rotation
+        mParam.gyroVar = DEFAULT_GYRO_VAR;
+        mParam.gyroBiasVar = DEFAULT_GYRO_BIAS_VAR;
+        mParam.accStdev = DEFAULT_ACC_STDEV;
+        mParam.magStdev = DEFAULT_MAG_STDEV;
+    } else {
+        mParam.gyroVar = GEOMAG_GYRO_VAR;
+        mParam.gyroBiasVar = GEOMAG_GYRO_BIAS_VAR;
+        mParam.accStdev = GEOMAG_ACC_STDEV;
+        mParam.magStdev = GEOMAG_MAG_STDEV;
+    }
 }
 
 void Fusion::initFusion(const vec4_t& q, float dT)
@@ -205,11 +235,11 @@
     const float dT3 = dT2*dT;
 
     // variance of integrated output at 1/dT Hz (random drift)
-    const float q00 = gyroVAR * dT + 0.33333f * biasVAR * dT3;
+    const float q00 = mParam.gyroVar * dT + 0.33333f * mParam.gyroBiasVar * dT3;
 
     // variance of drift rate ramp
-    const float q11 = biasVAR * dT;
-    const float q10 = 0.5f * biasVAR * dT2;
+    const float q11 = mParam.gyroBiasVar * dT;
+    const float q10 = 0.5f * mParam.gyroBiasVar * dT2;
     const float q01 = q10;
 
     GQGt[0][0] =  q00;      // rad^2
@@ -223,7 +253,9 @@
 }
 
 bool Fusion::hasEstimate() const {
-    return (mInitState == (MAG|ACC|GYRO));
+    return ((mInitState & MAG) || (mMode == FUSION_NOMAG)) &&
+           ((mInitState & GYRO) || (mMode == FUSION_NOGYRO)) &&
+           (mInitState & ACC);
 }
 
 bool Fusion::checkInitComplete(int what, const vec3_t& d, float dT) {
@@ -234,6 +266,9 @@
         mData[0] += d * (1/length(d));
         mCount[0]++;
         mInitState |= ACC;
+        if (mMode == FUSION_NOGYRO ) {
+            mGyroRate = dT;
+        }
     } else if (what == MAG) {
         mData[1] += d * (1/length(d));
         mCount[1]++;
@@ -242,25 +277,29 @@
         mGyroRate = dT;
         mData[2] += d*dT;
         mCount[2]++;
-        if (mCount[2] == 64) {
-            // 64 samples is good enough to estimate the gyro drift and
-            // doesn't take too much time.
-            mInitState |= GYRO;
-        }
+        mInitState |= GYRO;
     }
 
-    if (mInitState == (MAG|ACC|GYRO)) {
+    if (hasEstimate()) {
         // Average all the values we collected so far
         mData[0] *= 1.0f/mCount[0];
-        mData[1] *= 1.0f/mCount[1];
+        if (mMode != FUSION_NOMAG) {
+            mData[1] *= 1.0f/mCount[1];
+        }
         mData[2] *= 1.0f/mCount[2];
 
         // calculate the MRPs from the data collection, this gives us
         // a rough estimate of our initial state
         mat33_t R;
-        vec3_t up(mData[0]);
-        vec3_t east(cross_product(mData[1], up));
-        east *= 1/length(east);
+        vec3_t  up(mData[0]);
+        vec3_t  east;
+
+        if (mMode != FUSION_NOMAG) {
+            east = normalize(cross_product(mData[1], up));
+        } else {
+            east = getOrthogonal(up);
+        }
+
         vec3_t north(cross_product(up, east));
         R << east << north << up;
         const vec4_t q = matrixToQuat(R);
@@ -278,21 +317,43 @@
     predict(w, dT);
 }
 
-status_t Fusion::handleAcc(const vec3_t& a) {
+status_t Fusion::handleAcc(const vec3_t& a, float dT) {
+    if (!checkInitComplete(ACC, a, dT))
+        return BAD_VALUE;
+
     // ignore acceleration data if we're close to free-fall
-    if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) {
+    const float l = length(a);
+    if (l < FREE_FALL_THRESHOLD) {
         return BAD_VALUE;
     }
 
-    if (!checkInitComplete(ACC, a))
-        return BAD_VALUE;
+    const float l_inv = 1.0f/l;
 
-    const float l = 1/length(a);
-    update(a*l, Ba, accSTDEV*l);
+    if ( mMode == FUSION_NOGYRO ) {
+        //geo mag
+        vec3_t w_dummy;
+        w_dummy = x1; //bias
+        predict(w_dummy, dT);
+    }
+
+    if ( mMode == FUSION_NOMAG) {
+        vec3_t m;
+        m = getRotationMatrix()*Bm;
+        update(m, Bm, mParam.magStdev);
+    }
+
+    vec3_t unityA = a * l_inv;
+    const float d = sqrtf(fabsf(l- NOMINAL_GRAVITY));
+    const float p = l_inv * mParam.accStdev*expf(d);
+
+    update(unityA, Ba, p);
     return NO_ERROR;
 }
 
 status_t Fusion::handleMag(const vec3_t& m) {
+    if (!checkInitComplete(MAG, m))
+        return BAD_VALUE;
+
     // the geomagnetic-field should be between 30uT and 60uT
     // reject if too large to avoid spurious magnetic sources
     const float magFieldSq = length_squared(m);
@@ -304,9 +365,6 @@
         return BAD_VALUE;
     }
 
-    if (!checkInitComplete(MAG, m))
-        return BAD_VALUE;
-
     // Orthogonalize the magnetic field to the gravity field, mapping it into
     // tangent to Earth.
     const vec3_t up( getRotationMatrix() * Ba );
@@ -324,10 +382,10 @@
     // then pass it in as the update.
     vec3_t north( cross_product(up, east) );
 
-    const float l = 1 / length(north);
-    north *= l;
+    const float l_inv = 1 / length(north);
+    north *= l_inv;
 
-    update(north, Bm, magSTDEV*l);
+    update(north, Bm,  mParam.magStdev*l_inv);
     return NO_ERROR;
 }
 
@@ -372,8 +430,11 @@
 void Fusion::predict(const vec3_t& w, float dT) {
     const vec4_t q  = x0;
     const vec3_t b  = x1;
-    const vec3_t we = w - b;
+    vec3_t we = w - b;
 
+    if (length(we) < WVEC_EPS) {
+        we = (we[0]>0.f)?WVEC_EPS:-WVEC_EPS;
+    }
     // q(k+1) = O(we)*q(k)
     // --------------------
     //
@@ -406,7 +467,7 @@
     const mat33_t wx2(wx*wx);
     const float lwedT = length(we)*dT;
     const float hlwedT = 0.5f*lwedT;
-    const float ilwe = 1/length(we);
+    const float ilwe = 1.f/length(we);
     const float k0 = (1-cosf(lwedT))*(ilwe*ilwe);
     const float k1 = sinf(lwedT);
     const float k2 = cosf(hlwedT);
@@ -422,6 +483,7 @@
     Phi[1][0] = wx*k0 - I33dT - wx2*(ilwe*ilwe*ilwe)*(lwedT-k1);
 
     x0 = O*q;
+
     if (x0.w < 0)
         x0 = -x0;
 
@@ -466,15 +528,37 @@
 
     const vec3_t e(z - Bb);
     const vec3_t dq(K[0]*e);
-    const vec3_t db(K[1]*e);
 
     q += getF(q)*(0.5f*dq);
     x0 = normalize_quat(q);
-    x1 += db;
+
+    if (mMode != FUSION_NOMAG) {
+        const vec3_t db(K[1]*e);
+        x1 += db;
+    }
 
     checkState();
 }
 
+vec3_t Fusion::getOrthogonal(const vec3_t &v) {
+    vec3_t w;
+    if (fabsf(v[0])<= fabsf(v[1]) && fabsf(v[0]) <= fabsf(v[2]))  {
+        w[0]=0.f;
+        w[1] = v[2];
+        w[2] = -v[1];
+    } else if (fabsf(v[1]) <= fabsf(v[2])) {
+        w[0] = v[2];
+        w[1] = 0.f;
+        w[2] = -v[0];
+    }else {
+        w[0] = v[1];
+        w[1] = -v[0];
+        w[2] = 0.f;
+    }
+    return normalize(w);
+}
+
+
 // -----------------------------------------------------------------------
 
 }; // namespace android
diff --git a/services/sensorservice/Fusion.h b/services/sensorservice/Fusion.h
index 7062999..602779f 100644
--- a/services/sensorservice/Fusion.h
+++ b/services/sensorservice/Fusion.h
@@ -27,6 +27,13 @@
 
 typedef mat<float, 3, 4> mat34_t;
 
+enum FUSION_MODE{
+    FUSION_9AXIS, // use accel gyro mag
+    FUSION_NOMAG, // use accel gyro (game rotation, gravity)
+    FUSION_NOGYRO, // use accel mag (geomag rotation)
+    NUM_FUSION_MODE
+};
+
 class Fusion {
     /*
      * the state vector is made of two sub-vector containing respectively:
@@ -55,9 +62,9 @@
 
 public:
     Fusion();
-    void init();
+    void init(int mode = FUSION_9AXIS);
     void handleGyro(const vec3_t& w, float dT);
-    status_t handleAcc(const vec3_t& a);
+    status_t handleAcc(const vec3_t& a, float dT);
     status_t handleMag(const vec3_t& m);
     vec4_t getAttitude() const;
     vec3_t getBias() const;
@@ -65,12 +72,21 @@
     bool hasEstimate() const;
 
 private:
+    struct Parameter {
+        float gyroVar;
+        float gyroBiasVar;
+        float accStdev;
+        float magStdev;
+    } mParam;
+
     mat<mat33_t, 2, 2> Phi;
     vec3_t Ba, Bm;
     uint32_t mInitState;
     float mGyroRate;
     vec<vec3_t, 3> mData;
     size_t mCount[3];
+    int mMode;
+
     enum { ACC=0x1, MAG=0x2, GYRO=0x4 };
     bool checkInitComplete(int, const vec3_t& w, float d = 0);
     void initFusion(const vec4_t& q0, float dT);
@@ -78,6 +94,7 @@
     void predict(const vec3_t& w, float dT);
     void update(const vec3_t& z, const vec3_t& Bi, float sigma);
     static mat34_t getF(const vec4_t& p);
+    static vec3_t getOrthogonal(const vec3_t &v);
 };
 
 }; // namespace android
diff --git a/services/sensorservice/GravitySensor.cpp b/services/sensorservice/GravitySensor.cpp
index 3cb3745..9d8add1 100644
--- a/services/sensorservice/GravitySensor.cpp
+++ b/services/sensorservice/GravitySensor.cpp
@@ -29,27 +29,36 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-GravitySensor::GravitySensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
+GravitySensor::GravitySensor(sensor_t const* list, size_t count) {
     for (size_t i=0 ; i<count ; i++) {
         if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
             mAccelerometer = Sensor(list + i);
             break;
         }
     }
+
+    const sensor_t sensor = {
+        .name       = "Gravity Sensor",
+        .vendor     = "AOSP",
+        .version    = 3,
+        .handle     = '_grv',
+        .type       = SENSOR_TYPE_GRAVITY,
+        .maxRange   = GRAVITY_EARTH * 2,
+        .resolution = mAccelerometer.getResolution(),
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool GravitySensor::process(sensors_event_t* outEvent,
         const sensors_event_t& event)
 {
-    const static double NS2S = 1.0 / 1000000000.0;
     if (event.type == SENSOR_TYPE_ACCELEROMETER) {
         vec3_t g;
-        if (!mSensorFusion.hasEstimate())
+        if (!mSensorFusion.hasEstimate(FUSION_NOMAG))
             return false;
-        const mat33_t R(mSensorFusion.getRotationMatrix());
+        const mat33_t R(mSensorFusion.getRotationMatrix(FUSION_NOMAG));
         // FIXME: we need to estimate the length of gravity because
         // the accelerometer may have a small scaling error. This
         // translates to an offset in the linear-acceleration sensor.
@@ -67,26 +76,11 @@
 }
 
 status_t GravitySensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(ident, enabled);
+    return mSensorFusion.activate(FUSION_NOMAG, ident, enabled);
 }
 
 status_t GravitySensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(ident, ns);
-}
-
-Sensor GravitySensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Gravity Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_grv';
-    hwSensor.type       = SENSOR_TYPE_GRAVITY;
-    hwSensor.maxRange   = GRAVITY_EARTH * 2;
-    hwSensor.resolution = mAccelerometer.getResolution();
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
+    return mSensorFusion.setDelay(FUSION_NOMAG, ident, ns);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/GravitySensor.h b/services/sensorservice/GravitySensor.h
index ac177c4..8e33a73 100644
--- a/services/sensorservice/GravitySensor.h
+++ b/services/sensorservice/GravitySensor.h
@@ -31,19 +31,14 @@
 class SensorDevice;
 class SensorFusion;
 
-class GravitySensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
+class GravitySensor : public VirtualSensor {
     Sensor mAccelerometer;
 
 public:
     GravitySensor(sensor_t const* list, size_t count);
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
+    virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+    virtual status_t activate(void* ident, bool enabled) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/LinearAccelerationSensor.cpp b/services/sensorservice/LinearAccelerationSensor.cpp
index d5f20d2..d1cd732 100644
--- a/services/sensorservice/LinearAccelerationSensor.cpp
+++ b/services/sensorservice/LinearAccelerationSensor.cpp
@@ -29,10 +29,21 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mGravitySensor(list, count)
-{
+LinearAccelerationSensor::LinearAccelerationSensor(sensor_t const* list, size_t count) :
+        mGravitySensor(list, count) {
+    const Sensor &gsensor = mGravitySensor.getSensor();
+    const sensor_t sensor = {
+        .name       = "Linear Acceleration Sensor",
+        .vendor     = "AOSP",
+        .version    = gsensor.getVersion(),
+        .handle     = '_lin',
+        .type       = SENSOR_TYPE_LINEAR_ACCELERATION,
+        .maxRange   = gsensor.getMaxValue(),
+        .resolution = gsensor.getResolution(),
+        .power      = gsensor.getPowerUsage(),
+        .minDelay   = gsensor.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool LinearAccelerationSensor::process(sensors_event_t* outEvent,
@@ -58,22 +69,6 @@
     return mGravitySensor.setDelay(ident, handle, ns);
 }
 
-Sensor LinearAccelerationSensor::getSensor() const {
-    Sensor gsensor(mGravitySensor.getSensor());
-    sensor_t hwSensor;
-    hwSensor.name       = "Linear Acceleration Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = gsensor.getVersion();
-    hwSensor.handle     = '_lin';
-    hwSensor.type       = SENSOR_TYPE_LINEAR_ACCELERATION;
-    hwSensor.maxRange   = gsensor.getMaxValue();
-    hwSensor.resolution = gsensor.getResolution();
-    hwSensor.power      = gsensor.getPowerUsage();
-    hwSensor.minDelay   = gsensor.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
-}
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/LinearAccelerationSensor.h b/services/sensorservice/LinearAccelerationSensor.h
index 5deb24f..428baa6 100644
--- a/services/sensorservice/LinearAccelerationSensor.h
+++ b/services/sensorservice/LinearAccelerationSensor.h
@@ -32,18 +32,15 @@
 class SensorDevice;
 class SensorFusion;
 
-class LinearAccelerationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
+class LinearAccelerationSensor : public VirtualSensor {
     GravitySensor mGravitySensor;
 
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
 public:
     LinearAccelerationSensor(sensor_t const* list, size_t count);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
+    virtual status_t activate(void* ident, bool enabled) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.cpp b/services/sensorservice/OrientationSensor.cpp
index 6d85cca..ea5dbc9 100644
--- a/services/sensorservice/OrientationSensor.cpp
+++ b/services/sensorservice/OrientationSensor.cpp
@@ -29,13 +29,19 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-OrientationSensor::OrientationSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
-    // FIXME: instead of using the SensorFusion code, we should use
-    // the SENSOR_TYPE_ROTATION_VECTOR instead. This way we could use the
-    // HAL's implementation.
+OrientationSensor::OrientationSensor() {
+    const sensor_t sensor = {
+        .name       = "Orientation Sensor",
+        .vendor     = "AOSP",
+        .version    = 1,
+        .handle     = '_ypr',
+        .type       = SENSOR_TYPE_ORIENTATION,
+        .maxRange   = 360.0f,
+        .resolution = 1.0f/256.0f, // FIXME: real value here
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool OrientationSensor::process(sensors_event_t* outEvent,
@@ -66,26 +72,11 @@
 }
 
 status_t OrientationSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(ident, enabled);
+    return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
 }
 
 status_t OrientationSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(ident, ns);
-}
-
-Sensor OrientationSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Orientation Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_ypr';
-    hwSensor.type       = SENSOR_TYPE_ORIENTATION;
-    hwSensor.maxRange   = 360.0f;
-    hwSensor.resolution = 1.0f/256.0f; // FIXME: real value here
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
+    return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/OrientationSensor.h b/services/sensorservice/OrientationSensor.h
index 855949d..30ff226 100644
--- a/services/sensorservice/OrientationSensor.h
+++ b/services/sensorservice/OrientationSensor.h
@@ -31,18 +31,12 @@
 class SensorDevice;
 class SensorFusion;
 
-class OrientationSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
+class OrientationSensor : public VirtualSensor {
 public:
     OrientationSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
+    virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+    virtual status_t activate(void* ident, bool enabled) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RecentEventLogger.cpp b/services/sensorservice/RecentEventLogger.cpp
new file mode 100644
index 0000000..754b603
--- /dev/null
+++ b/services/sensorservice/RecentEventLogger.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 "RecentEventLogger.h"
+#include "SensorServiceUtils.h"
+
+#include <utils/Timers.h>
+
+#include <inttypes.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+namespace {
+    constexpr size_t LOG_SIZE = 10;
+    constexpr size_t LOG_SIZE_LARGE = 50;  // larger samples for debugging
+}// unnamed namespace
+
+RecentEventLogger::RecentEventLogger(int sensorType) :
+        mSensorType(sensorType), mEventSize(eventSizeBySensorType(mSensorType)),
+        mRecentEvents(logSizeBySensorType(sensorType)) {
+    // blank
+}
+
+void RecentEventLogger::addEvent(const sensors_event_t& event) {
+    std::lock_guard<std::mutex> lk(mLock);
+    mRecentEvents.emplace(event);
+}
+
+bool RecentEventLogger::isEmpty() const {
+    return mRecentEvents.size() == 0;
+}
+
+std::string RecentEventLogger::dump() const {
+    std::lock_guard<std::mutex> lk(mLock);
+
+    //TODO: replace String8 with std::string completely in this function
+    String8 buffer;
+
+    buffer.appendFormat("last %zu events\n", mRecentEvents.size());
+    int j = 0;
+    for (int i = mRecentEvents.size() - 1; i >= 0; --i) {
+        const auto& ev = mRecentEvents[i];
+        struct tm * timeinfo = localtime(&(ev.mWallTime.tv_sec));
+        buffer.appendFormat("\t%2d (ts=%.9f, wall=%02d:%02d:%02d.%03d) ",
+                ++j, ev.mEvent.timestamp/1e9, timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec,
+                (int) ns2ms(ev.mWallTime.tv_nsec));
+
+        // data
+        if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
+            buffer.appendFormat("%" PRIu64 ", ", ev.mEvent.u64.step_counter);
+        } else {
+            for (size_t k = 0; k < mEventSize; ++k) {
+                buffer.appendFormat("%.2f, ", ev.mEvent.data[k]);
+            }
+        }
+        buffer.append("\n");
+    }
+    return std::string(buffer.string());
+}
+
+bool RecentEventLogger::populateLastEvent(sensors_event_t *event) const {
+    std::lock_guard<std::mutex> lk(mLock);
+
+    if (mRecentEvents.size()) {
+        // Index 0 contains the latest event emplace()'ed
+        *event = mRecentEvents[0].mEvent;
+        return true;
+    } else {
+        return false;
+    }
+}
+
+
+size_t RecentEventLogger::logSizeBySensorType(int sensorType) {
+    return (sensorType == SENSOR_TYPE_STEP_COUNTER ||
+            sensorType == SENSOR_TYPE_SIGNIFICANT_MOTION ||
+            sensorType == SENSOR_TYPE_ACCELEROMETER) ? LOG_SIZE_LARGE : LOG_SIZE;
+}
+
+RecentEventLogger::SensorEventLog::SensorEventLog(const sensors_event_t& e) : mEvent(e) {
+    clock_gettime(CLOCK_REALTIME, &mWallTime);
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
diff --git a/services/sensorservice/RecentEventLogger.h b/services/sensorservice/RecentEventLogger.h
new file mode 100644
index 0000000..4f9bc4a
--- /dev/null
+++ b/services/sensorservice/RecentEventLogger.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+#define ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+
+#include "RingBuffer.h"
+#include "SensorServiceUtils.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+#include <mutex>
+
+namespace android {
+namespace SensorServiceUtil {
+
+// A circular buffer that record the last N events of a sensor type for debugging. The size of this
+// buffer depends on sensor type and is controlled by logSizeBySensorType(). The last N events
+// generated from the sensor are stored in this buffer.  The buffer is NOT cleared when the sensor
+// unregisters and as a result very old data in the dumpsys output can be seen, which is an intended
+// behavior.
+class RecentEventLogger : public Dumpable {
+public:
+    RecentEventLogger(int sensorType);
+    void addEvent(const sensors_event_t& event);
+    bool populateLastEvent(sensors_event_t *event) const;
+    bool isEmpty() const;
+    virtual ~RecentEventLogger() {}
+
+    // Dumpable interface
+    virtual std::string dump() const override;
+
+protected:
+    struct SensorEventLog {
+        SensorEventLog(const sensors_event_t& e);
+        timespec mWallTime;
+        sensors_event_t mEvent;
+    };
+
+    const int mSensorType;
+    const size_t mEventSize;
+
+    mutable std::mutex mLock;
+    RingBuffer<SensorEventLog> mRecentEvents;
+
+private:
+    static size_t logSizeBySensorType(int sensorType);
+};
+
+} // namespace SensorServiceUtil
+} // namespace android;
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_RECENT_EVENT_LOGGER_H
+
diff --git a/services/sensorservice/RingBuffer.h b/services/sensorservice/RingBuffer.h
new file mode 100644
index 0000000..ec98a01
--- /dev/null
+++ b/services/sensorservice/RingBuffer.h
@@ -0,0 +1,361 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+#define ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+
+#include <utils/Log.h>
+#include <cutils/compiler.h>
+
+#include <iterator>
+#include <utility>
+#include <vector>
+
+namespace android {
+namespace SensorServiceUtil {
+
+/**
+ * A RingBuffer class that maintains an array of objects that can grow up to a certain size.
+ * Elements added to the RingBuffer are inserted in the logical front of the buffer, and
+ * invalidate all current iterators for that RingBuffer object.
+ */
+template <class T>
+class RingBuffer final {
+public:
+
+    /**
+     * Construct a RingBuffer that can grow up to the given length.
+     */
+    RingBuffer(size_t length);
+
+    /**
+     * Forward iterator to this class.  Implements an std:forward_iterator.
+     */
+    class iterator : public std::iterator<std::forward_iterator_tag, T> {
+    public:
+        iterator(T* ptr, size_t size, size_t pos, size_t ctr);
+
+        iterator& operator++();
+
+        iterator operator++(int);
+
+        bool operator==(const iterator& rhs);
+
+        bool operator!=(const iterator& rhs);
+
+        T& operator*();
+
+        T* operator->();
+
+    private:
+        T* mPtr;
+        size_t mSize;
+        size_t mPos;
+        size_t mCtr;
+    };
+
+    /**
+     * Constant forward iterator to this class.  Implements an std:forward_iterator.
+     */
+    class const_iterator : public std::iterator<std::forward_iterator_tag, T> {
+    public:
+        const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr);
+
+        const_iterator& operator++();
+
+        const_iterator operator++(int);
+
+        bool operator==(const const_iterator& rhs);
+
+        bool operator!=(const const_iterator& rhs);
+
+        const T& operator*();
+
+        const T* operator->();
+
+    private:
+        const T* mPtr;
+        size_t mSize;
+        size_t mPos;
+        size_t mCtr;
+    };
+
+    /**
+     * Adds item to the front of this RingBuffer.  If the RingBuffer is at its maximum length,
+     * this will result in the last element being replaced (this is done using the element's
+     * assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    void add(const T& item);
+
+    /**
+     * Moves item to the front of this RingBuffer.  Following a call to this, item should no
+     * longer be used.  If the RingBuffer is at its maximum length, this will result in the
+     * last element being replaced (this is done using the element's assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    void add(T&& item);
+
+    /**
+     * Construct item in-place in the front of this RingBuffer using the given arguments.  If
+     * the RingBuffer is at its maximum length, this will result in the last element being
+     * replaced (this is done using the element's assignment operator).
+     *
+     * All current iterators are invalidated.
+     */
+    template <class... Args>
+    void emplace(Args&&... args);
+
+    /**
+     * Get an iterator to the front of this RingBuffer.
+     */
+    iterator begin();
+
+    /**
+     * Get an iterator to the end of this RingBuffer.
+     */
+    iterator end();
+
+    /**
+     * Get a const_iterator to the front of this RingBuffer.
+     */
+    const_iterator begin() const;
+
+    /**
+     * Get a const_iterator to the end of this RingBuffer.
+     */
+    const_iterator end() const;
+
+    /**
+     * Return a reference to the element at a given index.  If the index is out of range for
+     * this ringbuffer, [0, size), the behavior for this is undefined.
+     */
+    T& operator[](size_t index);
+
+    /**
+     * Return a const reference to the element at a given index.  If the index is out of range
+     * for this ringbuffer, [0, size), the behavior for this is undefined.
+     */
+    const T& operator[](size_t index) const;
+
+    /**
+     * Return the current size of this RingBuffer.
+     */
+    size_t size() const;
+
+    /**
+     * Remove all elements from this RingBuffer and set the size to 0.
+     */
+    void clear();
+
+private:
+    size_t mFrontIdx;
+    size_t mMaxBufferSize;
+    std::vector<T> mBuffer;
+}; // class RingBuffer
+
+
+template <class T>
+RingBuffer<T>::RingBuffer(size_t length) : mFrontIdx{0}, mMaxBufferSize{length} {}
+
+template <class T>
+RingBuffer<T>::iterator::iterator(T* ptr, size_t size, size_t pos, size_t ctr) :
+        mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::iterator& RingBuffer<T>::iterator::operator++() {
+    ++mCtr;
+
+    if (CC_UNLIKELY(mCtr == mSize)) {
+        mPos = mSize;
+        return *this;
+    }
+
+    mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+    return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::iterator::operator++(int) {
+    iterator tmp{mPtr, mSize, mPos, mCtr};
+    ++(*this);
+    return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator==(const iterator& rhs) {
+    return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::iterator::operator!=(const iterator& rhs) {
+    return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+T& RingBuffer<T>::iterator::operator*() {
+    return *(mPtr + mPos);
+}
+
+template <class T>
+T* RingBuffer<T>::iterator::operator->() {
+    return mPtr + mPos;
+}
+
+template <class T>
+RingBuffer<T>::const_iterator::const_iterator(const T* ptr, size_t size, size_t pos, size_t ctr) :
+        mPtr{ptr}, mSize{size}, mPos{pos}, mCtr{ctr} {}
+
+template <class T>
+typename RingBuffer<T>::const_iterator& RingBuffer<T>::const_iterator::operator++() {
+    ++mCtr;
+
+    if (CC_UNLIKELY(mCtr == mSize)) {
+        mPos = mSize;
+        return *this;
+    }
+
+    mPos = ((CC_UNLIKELY(mPos == 0)) ? mSize - 1 : mPos - 1);
+    return *this;
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::const_iterator::operator++(int) {
+    const_iterator tmp{mPtr, mSize, mPos, mCtr};
+    ++(*this);
+    return tmp;
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator==(const const_iterator& rhs) {
+    return (mPtr + mPos) == (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+bool RingBuffer<T>::const_iterator::operator!=(const const_iterator& rhs) {
+    return (mPtr + mPos) != (rhs.mPtr + rhs.mPos);
+}
+
+template <class T>
+const T& RingBuffer<T>::const_iterator::operator*() {
+    return *(mPtr + mPos);
+}
+
+template <class T>
+const T* RingBuffer<T>::const_iterator::operator->() {
+    return mPtr + mPos;
+}
+
+template <class T>
+void RingBuffer<T>::add(const T& item) {
+    if (mBuffer.size() < mMaxBufferSize) {
+        mBuffer.push_back(item);
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    mBuffer[mFrontIdx] = item;
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+void RingBuffer<T>::add(T&& item) {
+    if (mBuffer.size() != mMaxBufferSize) {
+        mBuffer.push_back(std::forward<T>(item));
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    // Only works for types with move assignment operator
+    mBuffer[mFrontIdx] = std::forward<T>(item);
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+template <class... Args>
+void RingBuffer<T>::emplace(Args&&... args) {
+    if (mBuffer.size() != mMaxBufferSize) {
+        mBuffer.emplace_back(std::forward<Args>(args)...);
+        mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+        return;
+    }
+
+    // Only works for types with move assignment operator
+    mBuffer[mFrontIdx] = T(std::forward<Args>(args)...);
+    mFrontIdx = ((mFrontIdx + 1) % mMaxBufferSize);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::begin() {
+    size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+    return iterator(mBuffer.data(), mBuffer.size(), (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::iterator RingBuffer<T>::end() {
+    size_t s = mBuffer.size();
+    return iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::begin() const {
+    size_t tmp = (mBuffer.size() == 0) ? 0 : mBuffer.size() - 1;
+    return const_iterator(mBuffer.data(), mBuffer.size(),
+            (mFrontIdx == 0) ? tmp : mFrontIdx - 1, 0);
+}
+
+template <class T>
+typename RingBuffer<T>::const_iterator RingBuffer<T>::end() const {
+    size_t s = mBuffer.size();
+    return const_iterator(mBuffer.data(), s, s, s);
+}
+
+template <class T>
+T& RingBuffer<T>::operator[](size_t index) {
+    LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+            index, mBuffer.size());
+    size_t pos = (index >= mFrontIdx) ?
+            mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+    return mBuffer[pos];
+}
+
+template <class T>
+const T& RingBuffer<T>::operator[](size_t index) const {
+    LOG_ALWAYS_FATAL_IF(index >= mBuffer.size(), "Index %zu out of bounds, size is %zu.",
+            index, mBuffer.size());
+    size_t pos = (index >= mFrontIdx) ?
+            mBuffer.size() - 1 - (index - mFrontIdx) : mFrontIdx - 1 - index;
+    return mBuffer[pos];
+}
+
+template <class T>
+size_t RingBuffer<T>::size() const {
+    return mBuffer.size();
+}
+
+template <class T>
+void RingBuffer<T>::clear() {
+    mBuffer.clear();
+    mFrontIdx = 0;
+}
+
+}  // namespace SensorServiceUtil
+}; // namespace android
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_RING_BUFFER_H
+
diff --git a/services/sensorservice/RotationVectorSensor.cpp b/services/sensorservice/RotationVectorSensor.cpp
index cb305eb..7b00f4d 100644
--- a/services/sensorservice/RotationVectorSensor.cpp
+++ b/services/sensorservice/RotationVectorSensor.cpp
@@ -27,25 +27,35 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-RotationVectorSensor::RotationVectorSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
+RotationVectorSensor::RotationVectorSensor(int mode) :
+      mMode(mode) {
+    const sensor_t sensor = {
+        .name       = getSensorName(),
+        .vendor     = "AOSP",
+        .version    = 3,
+        .handle     = getSensorToken(),
+        .type       = getSensorType(),
+        .maxRange   = 1,
+        .resolution = 1.0f / (1<<24),
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool RotationVectorSensor::process(sensors_event_t* outEvent,
         const sensors_event_t& event)
 {
     if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        if (mSensorFusion.hasEstimate()) {
-            const vec4_t q(mSensorFusion.getAttitude());
+        if (mSensorFusion.hasEstimate(mMode)) {
+            const vec4_t q(mSensorFusion.getAttitude(mMode));
             *outEvent = event;
             outEvent->data[0] = q.x;
             outEvent->data[1] = q.y;
             outEvent->data[2] = q.z;
             outEvent->data[3] = q.w;
-            outEvent->sensor = '_rov';
-            outEvent->type = SENSOR_TYPE_ROTATION_VECTOR;
+            outEvent->sensor = getSensorToken();
+            outEvent->type = getSensorType();
             return true;
         }
     }
@@ -53,34 +63,70 @@
 }
 
 status_t RotationVectorSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(ident, enabled);
+    return mSensorFusion.activate(mMode, ident, enabled);
 }
 
 status_t RotationVectorSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(ident, ns);
+    return mSensorFusion.setDelay(mMode, ident, ns);
 }
 
-Sensor RotationVectorSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Rotation Vector Sensor";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 3;
-    hwSensor.handle     = '_rov';
-    hwSensor.type       = SENSOR_TYPE_ROTATION_VECTOR;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
+int RotationVectorSensor::getSensorType() const {
+    switch(mMode) {
+        case FUSION_9AXIS:
+            return SENSOR_TYPE_ROTATION_VECTOR;
+        case FUSION_NOMAG:
+            return SENSOR_TYPE_GAME_ROTATION_VECTOR;
+        case FUSION_NOGYRO:
+            return SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR;
+        default:
+            assert(0);
+            return 0;
+    }
+}
+
+const char* RotationVectorSensor::getSensorName() const {
+    switch(mMode) {
+        case FUSION_9AXIS:
+            return "Rotation Vector Sensor";
+        case FUSION_NOMAG:
+            return "Game Rotation Vector Sensor";
+        case FUSION_NOGYRO:
+            return "GeoMag Rotation Vector Sensor";
+        default:
+            assert(0);
+            return NULL;
+    }
+}
+
+int RotationVectorSensor::getSensorToken() const {
+    switch(mMode) {
+        case FUSION_9AXIS:
+            return '_rov';
+        case FUSION_NOMAG:
+            return '_gar';
+        case FUSION_NOGYRO:
+            return '_geo';
+        default:
+            assert(0);
+            return 0;
+    }
 }
 
 // ---------------------------------------------------------------------------
 
-GyroDriftSensor::GyroDriftSensor()
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensorFusion(SensorFusion::getInstance())
-{
+GyroDriftSensor::GyroDriftSensor() {
+    const sensor_t sensor = {
+        .name       = "Gyroscope Bias (debug)",
+        .vendor     = "AOSP",
+        .version    = 1,
+        .handle     = '_gbs',
+        .type       = SENSOR_TYPE_ACCELEROMETER,
+        .maxRange   = 1,
+        .resolution = 1.0f / (1<<24),
+        .power      = mSensorFusion.getPowerUsage(),
+        .minDelay   = mSensorFusion.getMinDelay(),
+    };
+    mSensor = Sensor(&sensor);
 }
 
 bool GyroDriftSensor::process(sensors_event_t* outEvent,
@@ -102,26 +148,11 @@
 }
 
 status_t GyroDriftSensor::activate(void* ident, bool enabled) {
-    return mSensorFusion.activate(ident, enabled);
+    return mSensorFusion.activate(FUSION_9AXIS, ident, enabled);
 }
 
 status_t GyroDriftSensor::setDelay(void* ident, int /*handle*/, int64_t ns) {
-    return mSensorFusion.setDelay(ident, ns);
-}
-
-Sensor GyroDriftSensor::getSensor() const {
-    sensor_t hwSensor;
-    hwSensor.name       = "Gyroscope Bias (debug)";
-    hwSensor.vendor     = "AOSP";
-    hwSensor.version    = 1;
-    hwSensor.handle     = '_gbs';
-    hwSensor.type       = SENSOR_TYPE_ACCELEROMETER;
-    hwSensor.maxRange   = 1;
-    hwSensor.resolution = 1.0f / (1<<24);
-    hwSensor.power      = mSensorFusion.getPowerUsage();
-    hwSensor.minDelay   = mSensorFusion.getMinDelay();
-    Sensor sensor(&hwSensor);
-    return sensor;
+    return mSensorFusion.setDelay(FUSION_9AXIS, ident, ns);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/RotationVectorSensor.h b/services/sensorservice/RotationVectorSensor.h
index bb97fe1..3cc2248 100644
--- a/services/sensorservice/RotationVectorSensor.h
+++ b/services/sensorservice/RotationVectorSensor.h
@@ -32,32 +32,36 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-class RotationVectorSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
-
+class RotationVectorSensor : public VirtualSensor {
 public:
-    RotationVectorSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
+    RotationVectorSensor(int mode = FUSION_9AXIS);
+    virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+    virtual status_t activate(void* ident, bool enabled) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+
+protected:
+    const int mMode;
+    int getSensorType() const;
+    const char* getSensorName() const ;
+    int getSensorToken() const ;
 };
 
-class GyroDriftSensor : public SensorInterface {
-    SensorDevice& mSensorDevice;
-    SensorFusion& mSensorFusion;
+class GameRotationVectorSensor : public RotationVectorSensor {
+public:
+    GameRotationVectorSensor() : RotationVectorSensor(FUSION_NOMAG) {}
+};
 
+class GeoMagRotationVectorSensor : public RotationVectorSensor {
+public:
+    GeoMagRotationVectorSensor() : RotationVectorSensor(FUSION_NOGYRO) {}
+};
+
+class GyroDriftSensor : public VirtualSensor {
 public:
     GyroDriftSensor();
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event);
-    virtual status_t activate(void* ident, bool enabled);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return true; }
+    virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) override;
+    virtual status_t activate(void* ident, bool enabled) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index dd1bccf..4fbaa50 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -39,8 +39,7 @@
 
 SensorDevice::SensorDevice()
     :  mSensorDevice(0),
-       mSensorModule(0)
-{
+       mSensorModule(0) {
     status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
             (hw_module_t const**)&mSensorModule);
 
@@ -73,37 +72,54 @@
     }
 }
 
-void SensorDevice::dump(String8& result)
-{
-    if (!mSensorModule) return;
-    sensor_t const* list;
-    ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+void SensorDevice::handleDynamicSensorConnection(int handle, bool connected) {
+    if (connected) {
+        Info model;
+        mActivationCount.add(handle, model);
+        mSensorDevice->activate(
+                reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), handle, 0);
+    } else {
+        mActivationCount.removeItem(handle);
+    }
+}
 
-    result.appendFormat("halVersion 0x%08x\n", getHalDeviceVersion());
-    result.appendFormat("%d h/w sensors:\n", int(count));
+std::string SensorDevice::dump() const {
+    if (!mSensorModule) return "HAL not initialized\n";
+
+    String8 result;
+    sensor_t const* list;
+    int count = mSensorModule->get_sensors_list(mSensorModule, &list);
+
+    result.appendFormat("HAL: %s (%s), version %#010x\n",
+                        mSensorModule->common.name,
+                        mSensorModule->common.author,
+                        getHalDeviceVersion());
+    result.appendFormat("Total %d h/w sensors, %zu running:\n", count, mActivationCount.size());
 
     Mutex::Autolock _l(mLock);
-    for (size_t i=0 ; i<size_t(count) ; i++) {
+    for (int i = 0 ; i < count ; i++) {
         const Info& info = mActivationCount.valueFor(list[i].handle);
         if (info.batchParams.isEmpty()) continue;
-        result.appendFormat("handle=0x%08x, active-count=%zu, batch_period(ms)={ ", list[i].handle,
+        result.appendFormat("0x%08x) active-count = %zu; ", list[i].handle,
                             info.batchParams.size());
+
+        result.append("sampling_period(ms) = {");
         for (size_t j = 0; j < info.batchParams.size(); j++) {
             const BatchParams& params = info.batchParams.valueAt(j);
-            result.appendFormat("%4.1f%s", params.batchDelay / 1e6f,
+            result.appendFormat("%.1f%s", params.batchDelay / 1e6f,
                                 j < info.batchParams.size() - 1 ? ", " : "");
         }
-        result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchDelay / 1e6f);
+        result.appendFormat("}, selected = %.1f ms; ", info.bestBatchParams.batchDelay / 1e6f);
 
-        result.appendFormat("handle=0x%08x, active-count=%zu, batch_timeout(ms)={ ", list[i].handle,
-                            info.batchParams.size());
+        result.append("batching_period(ms) = {");
         for (size_t j = 0; j < info.batchParams.size(); j++) {
             BatchParams params = info.batchParams.valueAt(j);
-            result.appendFormat("%4.1f%s", params.batchTimeout / 1e6f,
+            result.appendFormat("%.1f%s", params.batchTimeout / 1e6f,
                                 j < info.batchParams.size() - 1 ? ", " : "");
         }
-        result.appendFormat(" }, selected=%4.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
+        result.appendFormat("}, selected = %.1f ms\n", info.bestBatchParams.batchTimeout / 1e6f);
     }
+    return result.string();
 }
 
 ssize_t SensorDevice::getSensorList(sensor_t const** list) {
@@ -132,8 +148,7 @@
     info.removeBatchParamsForIdent(ident);
 }
 
-status_t SensorDevice::activate(void* ident, int handle, int enabled)
-{
+status_t SensorDevice::activate(void* ident, int handle, int enabled) {
     if (!mSensorDevice) return NO_INIT;
     status_t err(NO_ERROR);
     bool actuateHardware = false;
@@ -282,8 +297,7 @@
     return err;
 }
 
-status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs)
-{
+status_t SensorDevice::setDelay(void* ident, int handle, int64_t samplingPeriodNs) {
     if (!mSensorDevice) return NO_INIT;
     if (samplingPeriodNs < MINIMUM_EVENTS_PERIOD) {
         samplingPeriodNs = MINIMUM_EVENTS_PERIOD;
@@ -388,7 +402,7 @@
 
 status_t SensorDevice::injectSensorData(const sensors_event_t *injected_sensor_event) {
       ALOGD_IF(DEBUG_CONNECTIONS,
-              "sensor_event handle=%d ts=%lld data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
+              "sensor_event handle=%d ts=%" PRId64 " data=%.2f, %.2f, %.2f %.2f %.2f %.2f",
                injected_sensor_event->sensor,
                injected_sensor_event->timestamp, injected_sensor_event->data[0],
                injected_sensor_event->data[1], injected_sensor_event->data[2],
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index c484849..68bb853 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -17,21 +17,44 @@
 #ifndef ANDROID_SENSOR_DEVICE_H
 #define ANDROID_SENSOR_DEVICE_H
 
-#include <stdint.h>
-#include <sys/types.h>
+#include "SensorServiceUtils.h"
 
+#include <gui/Sensor.h>
 #include <utils/KeyedVector.h>
 #include <utils/Singleton.h>
 #include <utils/String8.h>
 
-#include <gui/Sensor.h>
+#include <stdint.h>
+#include <sys/types.h>
 
 // ---------------------------------------------------------------------------
 
 namespace android {
 // ---------------------------------------------------------------------------
+using SensorServiceUtil::Dumpable;
 
-class SensorDevice : public Singleton<SensorDevice> {
+class SensorDevice : public Singleton<SensorDevice>, public Dumpable {
+public:
+    ssize_t getSensorList(sensor_t const** list);
+    void handleDynamicSensorConnection(int handle, bool connected);
+    status_t initCheck() const;
+    int getHalDeviceVersion() const;
+    ssize_t poll(sensors_event_t* buffer, size_t count);
+    status_t activate(void* ident, int handle, int enabled);
+    status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
+                   int64_t maxBatchReportLatencyNs);
+    // Call batch with timeout zero instead of calling setDelay() for newer devices.
+    status_t setDelay(void* ident, int handle, int64_t ns);
+    status_t flush(void* ident, int handle);
+    status_t setMode(uint32_t mode);
+    void disableAllSensors();
+    void enableAllSensors();
+    void autoDisable(void *ident, int handle);
+    status_t injectSensorData(const sensors_event_t *event);
+
+    // Dumpable
+    virtual std::string dump() const;
+private:
     friend class Singleton<SensorDevice>;
     sensors_poll_device_1_t* mSensorDevice;
     struct sensors_module_t* mSensorModule;
@@ -87,23 +110,6 @@
 
     bool isClientDisabled(void* ident);
     bool isClientDisabledLocked(void* ident);
-public:
-    ssize_t getSensorList(sensor_t const** list);
-    status_t initCheck() const;
-    int getHalDeviceVersion() const;
-    ssize_t poll(sensors_event_t* buffer, size_t count);
-    status_t activate(void* ident, int handle, int enabled);
-    status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
-                   int64_t maxBatchReportLatencyNs);
-    // Call batch with timeout zero instead of calling setDelay() for newer devices.
-    status_t setDelay(void* ident, int handle, int64_t ns);
-    status_t flush(void* ident, int handle);
-    status_t setMode(uint32_t mode);
-    void disableAllSensors();
-    void enableAllSensors();
-    void autoDisable(void *ident, int handle);
-    status_t injectSensorData(const sensors_event_t *event);
-    void dump(String8& result);
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorEventAckReceiver.h b/services/sensorservice/SensorEventAckReceiver.h
new file mode 100644
index 0000000..998597a
--- /dev/null
+++ b/services/sensorservice/SensorEventAckReceiver.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_EVENT_ACK_RECEIVER_H
+#define ANDROID_SENSOR_EVENT_ACK_RECEIVER_H
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+class SensorService::SensorEventAckReceiver : public Thread {
+    sp<SensorService> const mService;
+public:
+    virtual bool threadLoop();
+    SensorEventAckReceiver(const sp<SensorService>& service)
+            : mService(service) {
+    }
+};
+
+}
+
+#endif // ANDROID_SENSOR_EVNET_ACK_RECEIVER_H
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
new file mode 100644
index 0000000..c1e1bad
--- /dev/null
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -0,0 +1,650 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 <sys/socket.h>
+#include <utils/threads.h>
+
+#include <gui/SensorEventQueue.h>
+
+#include "vec.h"
+#include "SensorEventConnection.h"
+#include "SensorDevice.h"
+
+namespace android {
+
+SensorService::SensorEventConnection::SensorEventConnection(
+        const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
+        const String16& opPackageName)
+    : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
+      mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
+      mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName) {
+    mChannel = new BitTube(mService->mSocketBufferSize);
+#if DEBUG_CONNECTIONS
+    mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
+    mTotalAcksNeeded = mTotalAcksReceived = 0;
+#endif
+}
+
+SensorService::SensorEventConnection::~SensorEventConnection() {
+    ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
+    mService->cleanupConnection(this);
+    if (mEventCache != NULL) {
+        delete mEventCache;
+    }
+}
+
+void SensorService::SensorEventConnection::onFirstRef() {
+    LooperCallback::onFirstRef();
+}
+
+bool SensorService::SensorEventConnection::needsWakeLock() {
+    Mutex::Autolock _l(mConnectionLock);
+    return !mDead && mWakeLockRefCount > 0;
+}
+
+void SensorService::SensorEventConnection::resetWakeLockRefCount() {
+    Mutex::Autolock _l(mConnectionLock);
+    mWakeLockRefCount = 0;
+}
+
+void SensorService::SensorEventConnection::dump(String8& result) {
+    Mutex::Autolock _l(mConnectionLock);
+    result.appendFormat("\tOperating Mode: %s\n",mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
+    result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
+            "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
+            mMaxCacheSize);
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
+        result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
+                            mService->getSensorName(mSensorInfo.keyAt(i)).string(),
+                            mSensorInfo.keyAt(i),
+                            flushInfo.mFirstFlushPending ? "First flush pending" :
+                                                           "active",
+                            flushInfo.mPendingFlushEventsToSend);
+    }
+#if DEBUG_CONNECTIONS
+    result.appendFormat("\t events recvd: %d | sent %d | cache %d | dropped %d |"
+            " total_acks_needed %d | total_acks_recvd %d\n",
+            mEventsReceived,
+            mEventsSent,
+            mEventsSentFromCache,
+            mEventsReceived - (mEventsSentFromCache + mEventsSent + mCacheSize),
+            mTotalAcksNeeded,
+            mTotalAcksReceived);
+#endif
+}
+
+bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+    if (si == nullptr ||
+        !canAccessSensor(si->getSensor(), "Tried adding", mOpPackageName) ||
+        mSensorInfo.indexOfKey(handle) >= 0) {
+        return false;
+    }
+    mSensorInfo.add(handle, FlushInfo());
+    return true;
+}
+
+bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    if (mSensorInfo.removeItem(handle) >= 0) {
+        return true;
+    }
+    return false;
+}
+
+bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
+    Mutex::Autolock _l(mConnectionLock);
+    return mSensorInfo.indexOfKey(handle) >= 0;
+}
+
+bool SensorService::SensorEventConnection::hasAnySensor() const {
+    Mutex::Autolock _l(mConnectionLock);
+    return mSensorInfo.size() ? true : false;
+}
+
+bool SensorService::SensorEventConnection::hasOneShotSensors() const {
+    Mutex::Autolock _l(mConnectionLock);
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const int handle = mSensorInfo.keyAt(i);
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si != nullptr && si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+            return true;
+        }
+    }
+    return false;
+}
+
+String8 SensorService::SensorEventConnection::getPackageName() const {
+    return mPackageName;
+}
+
+void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
+                                bool value) {
+    Mutex::Autolock _l(mConnectionLock);
+    ssize_t index = mSensorInfo.indexOfKey(handle);
+    if (index >= 0) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+        flushInfo.mFirstFlushPending = value;
+    }
+}
+
+void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {
+    Mutex::Autolock _l(mConnectionLock);
+    updateLooperRegistrationLocked(looper);
+}
+
+void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
+        const sp<Looper>& looper) {
+    bool isConnectionActive = (mSensorInfo.size() > 0 && !mDataInjectionMode) ||
+                              mDataInjectionMode;
+    // If all sensors are unregistered OR Looper has encountered an error, we can remove the Fd from
+    // the Looper if it has been previously added.
+    if (!isConnectionActive || mDead) { if (mHasLooperCallbacks) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "%p removeFd fd=%d", this,
+                 mChannel->getSendFd());
+        looper->removeFd(mChannel->getSendFd()); mHasLooperCallbacks = false; }
+    return; }
+
+    int looper_flags = 0;
+    if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
+    if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const int handle = mSensorInfo.keyAt(i);
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si != nullptr && si->getSensor().isWakeUpSensor()) {
+            looper_flags |= ALOOPER_EVENT_INPUT;
+        }
+    }
+
+    // If flags is still set to zero, we don't need to add this fd to the Looper, if the fd has
+    // already been added, remove it. This is likely to happen when ALL the events stored in the
+    // cache have been sent to the corresponding app.
+    if (looper_flags == 0) {
+        if (mHasLooperCallbacks) {
+            ALOGD_IF(DEBUG_CONNECTIONS, "removeFd fd=%d", mChannel->getSendFd());
+            looper->removeFd(mChannel->getSendFd());
+            mHasLooperCallbacks = false;
+        }
+        return;
+    }
+
+    // Add the file descriptor to the Looper for receiving acknowledegments if the app has
+    // registered for wake-up sensors OR for sending events in the cache.
+    int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, NULL);
+    if (ret == 1) {
+        ALOGD_IF(DEBUG_CONNECTIONS, "%p addFd fd=%d", this, mChannel->getSendFd());
+        mHasLooperCallbacks = true;
+    } else {
+        ALOGE("Looper::addFd failed ret=%d fd=%d", ret, mChannel->getSendFd());
+    }
+}
+
+void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
+    Mutex::Autolock _l(mConnectionLock);
+    ssize_t index = mSensorInfo.indexOfKey(handle);
+    if (index >= 0) {
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+        flushInfo.mPendingFlushEventsToSend++;
+    }
+}
+
+status_t SensorService::SensorEventConnection::sendEvents(
+        sensors_event_t const* buffer, size_t numEvents,
+        sensors_event_t* scratch,
+        SensorEventConnection const * const * mapFlushEventsToConnections) {
+    // filter out events not for this connection
+    int count = 0;
+    Mutex::Autolock _l(mConnectionLock);
+    if (scratch) {
+        size_t i=0;
+        while (i<numEvents) {
+            int32_t sensor_handle = buffer[i].sensor;
+            if (buffer[i].type == SENSOR_TYPE_META_DATA) {
+                ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
+                        buffer[i].meta_data.sensor);
+                // Setting sensor_handle to the correct sensor to ensure the sensor events per
+                // connection are filtered correctly.  buffer[i].sensor is zero for meta_data
+                // events.
+                sensor_handle = buffer[i].meta_data.sensor;
+            }
+
+            ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
+            // Check if this connection has registered for this sensor. If not continue to the
+            // next sensor_event.
+            if (index < 0) {
+                ++i;
+                continue;
+            }
+
+            FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
+            // Check if there is a pending flush_complete event for this sensor on this connection.
+            if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
+                    this == mapFlushEventsToConnections[i]) {
+                flushInfo.mFirstFlushPending = false;
+                ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
+                        buffer[i].meta_data.sensor);
+                ++i;
+                continue;
+            }
+
+            // If there is a pending flush complete event for this sensor on this connection,
+            // ignore the event and proceed to the next.
+            if (flushInfo.mFirstFlushPending) {
+                ++i;
+                continue;
+            }
+
+            do {
+                // Keep copying events into the scratch buffer as long as they are regular
+                // sensor_events are from the same sensor_handle OR they are flush_complete_events
+                // from the same sensor_handle AND the current connection is mapped to the
+                // corresponding flush_complete_event.
+                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
+                    if (this == mapFlushEventsToConnections[i]) {
+                        scratch[count++] = buffer[i];
+                    }
+                    ++i;
+                } else {
+                    // Regular sensor event, just copy it to the scratch buffer.
+                    scratch[count++] = buffer[i++];
+                }
+            } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle &&
+                                        buffer[i].type != SENSOR_TYPE_META_DATA) ||
+                                       (buffer[i].type == SENSOR_TYPE_META_DATA  &&
+                                        buffer[i].meta_data.sensor == sensor_handle)));
+        }
+    } else {
+        scratch = const_cast<sensors_event_t *>(buffer);
+        count = numEvents;
+    }
+
+    sendPendingFlushEventsLocked();
+    // Early return if there are no events for this connection.
+    if (count == 0) {
+        return status_t(NO_ERROR);
+    }
+
+#if DEBUG_CONNECTIONS
+     mEventsReceived += count;
+#endif
+    if (mCacheSize != 0) {
+        // There are some events in the cache which need to be sent first. Copy this buffer to
+        // the end of cache.
+        if (mCacheSize + count <= mMaxCacheSize) {
+            memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
+            mCacheSize += count;
+        } else {
+            // Check if any new sensors have registered on this connection which may have increased
+            // the max cache size that is desired.
+            if (mCacheSize + count < computeMaxCacheSizeLocked()) {
+                reAllocateCacheLocked(scratch, count);
+                return status_t(NO_ERROR);
+            }
+            // Some events need to be dropped.
+            int remaningCacheSize = mMaxCacheSize - mCacheSize;
+            if (remaningCacheSize != 0) {
+                memcpy(&mEventCache[mCacheSize], scratch,
+                                                remaningCacheSize * sizeof(sensors_event_t));
+            }
+            int numEventsDropped = count - remaningCacheSize;
+            countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
+            // Drop the first "numEventsDropped" in the cache.
+            memmove(mEventCache, &mEventCache[numEventsDropped],
+                    (mCacheSize - numEventsDropped) * sizeof(sensors_event_t));
+
+            // Copy the remainingEvents in scratch buffer to the end of cache.
+            memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
+                                            numEventsDropped * sizeof(sensors_event_t));
+        }
+        return status_t(NO_ERROR);
+    }
+
+    int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
+    if (index_wake_up_event >= 0) {
+        scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+        ++mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+        ++mTotalAcksNeeded;
+#endif
+    }
+
+    // NOTE: ASensorEvent and sensors_event_t are the same type.
+    ssize_t size = SensorEventQueue::write(mChannel,
+                                    reinterpret_cast<ASensorEvent const*>(scratch), count);
+    if (size < 0) {
+        // Write error, copy events to local cache.
+        if (index_wake_up_event >= 0) {
+            // If there was a wake_up sensor_event, reset the flag.
+            scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            if (mWakeLockRefCount > 0) {
+                --mWakeLockRefCount;
+            }
+#if DEBUG_CONNECTIONS
+            --mTotalAcksNeeded;
+#endif
+        }
+        if (mEventCache == NULL) {
+            mMaxCacheSize = computeMaxCacheSizeLocked();
+            mEventCache = new sensors_event_t[mMaxCacheSize];
+            mCacheSize = 0;
+        }
+        memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
+        mCacheSize += count;
+
+        // Add this file descriptor to the looper to get a callback when this fd is available for
+        // writing.
+        updateLooperRegistrationLocked(mService->getLooper());
+        return size;
+    }
+
+#if DEBUG_CONNECTIONS
+    if (size > 0) {
+        mEventsSent += count;
+    }
+#endif
+
+    return size < 0 ? status_t(size) : status_t(NO_ERROR);
+}
+
+void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
+                                                                 int count) {
+    sensors_event_t *eventCache_new;
+    const int new_cache_size = computeMaxCacheSizeLocked();
+    // Allocate new cache, copy over events from the old cache & scratch, free up memory.
+    eventCache_new = new sensors_event_t[new_cache_size];
+    memcpy(eventCache_new, mEventCache, mCacheSize * sizeof(sensors_event_t));
+    memcpy(&eventCache_new[mCacheSize], scratch, count * sizeof(sensors_event_t));
+
+    ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize,
+            new_cache_size);
+
+    delete mEventCache;
+    mEventCache = eventCache_new;
+    mCacheSize += count;
+    mMaxCacheSize = new_cache_size;
+}
+
+void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
+    ASensorEvent flushCompleteEvent;
+    memset(&flushCompleteEvent, 0, sizeof(flushCompleteEvent));
+    flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
+    // Loop through all the sensors for this connection and check if there are any pending
+    // flush complete events to be sent.
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        const int handle = mSensorInfo.keyAt(i);
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+        if (si == nullptr) {
+            continue;
+        }
+
+        FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
+        while (flushInfo.mPendingFlushEventsToSend > 0) {
+            flushCompleteEvent.meta_data.sensor = handle;
+            bool wakeUpSensor = si->getSensor().isWakeUpSensor();
+            if (wakeUpSensor) {
+               ++mWakeLockRefCount;
+               flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            }
+            ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
+            if (size < 0) {
+                if (wakeUpSensor) --mWakeLockRefCount;
+                return;
+            }
+            ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
+                    flushCompleteEvent.meta_data.sensor);
+            flushInfo.mPendingFlushEventsToSend--;
+        }
+    }
+}
+
+void SensorService::SensorEventConnection::writeToSocketFromCache() {
+    // At a time write at most half the size of the receiver buffer in SensorEventQueue OR
+    // half the size of the socket buffer allocated in BitTube whichever is smaller.
+    const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
+            int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
+    Mutex::Autolock _l(mConnectionLock);
+    // Send pending flush complete events (if any)
+    sendPendingFlushEventsLocked();
+    for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
+        const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize);
+        int index_wake_up_event =
+                  findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
+        if (index_wake_up_event >= 0) {
+            mEventCache[index_wake_up_event + numEventsSent].flags |=
+                    WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+            ++mWakeLockRefCount;
+#if DEBUG_CONNECTIONS
+            ++mTotalAcksNeeded;
+#endif
+        }
+
+        ssize_t size = SensorEventQueue::write(mChannel,
+                          reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
+                          numEventsToWrite);
+        if (size < 0) {
+            if (index_wake_up_event >= 0) {
+                // If there was a wake_up sensor_event, reset the flag.
+                mEventCache[index_wake_up_event + numEventsSent].flags  &=
+                        ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
+                if (mWakeLockRefCount > 0) {
+                    --mWakeLockRefCount;
+                }
+#if DEBUG_CONNECTIONS
+                --mTotalAcksNeeded;
+#endif
+            }
+            memmove(mEventCache, &mEventCache[numEventsSent],
+                                 (mCacheSize - numEventsSent) * sizeof(sensors_event_t));
+            ALOGD_IF(DEBUG_CONNECTIONS, "wrote %d events from cache size==%d ",
+                    numEventsSent, mCacheSize);
+            mCacheSize -= numEventsSent;
+            return;
+        }
+        numEventsSent += numEventsToWrite;
+#if DEBUG_CONNECTIONS
+        mEventsSentFromCache += numEventsToWrite;
+#endif
+    }
+    ALOGD_IF(DEBUG_CONNECTIONS, "wrote all events from cache size=%d ", mCacheSize);
+    // All events from the cache have been sent. Reset cache size to zero.
+    mCacheSize = 0;
+    // There are no more events in the cache. We don't need to poll for write on the fd.
+    // Update Looper registration.
+    updateLooperRegistrationLocked(mService->getLooper());
+}
+
+void SensorService::SensorEventConnection::countFlushCompleteEventsLocked(
+                sensors_event_t const* scratch, const int numEventsDropped) {
+    ALOGD_IF(DEBUG_CONNECTIONS, "dropping %d events ", numEventsDropped);
+    // Count flushComplete events in the events that are about to the dropped. These will be sent
+    // separately before the next batch of events.
+    for (int j = 0; j < numEventsDropped; ++j) {
+        if (scratch[j].type == SENSOR_TYPE_META_DATA) {
+            FlushInfo& flushInfo = mSensorInfo.editValueFor(scratch[j].meta_data.sensor);
+            flushInfo.mPendingFlushEventsToSend++;
+            ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
+                     flushInfo.mPendingFlushEventsToSend);
+        }
+    }
+    return;
+}
+
+int SensorService::SensorEventConnection::findWakeUpSensorEventLocked(
+                       sensors_event_t const* scratch, const int count) {
+    for (int i = 0; i < count; ++i) {
+        if (mService->isWakeUpSensorEvent(scratch[i])) {
+            return i;
+        }
+    }
+    return -1;
+}
+
+sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
+{
+    return mChannel;
+}
+
+status_t SensorService::SensorEventConnection::enableDisable(
+        int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
+        int reservedFlags)
+{
+    status_t err;
+    if (enabled) {
+        err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
+                               reservedFlags, mOpPackageName);
+
+    } else {
+        err = mService->disable(this, handle);
+    }
+    return err;
+}
+
+status_t SensorService::SensorEventConnection::setEventRate(
+        int handle, nsecs_t samplingPeriodNs)
+{
+    return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+}
+
+status_t  SensorService::SensorEventConnection::flush() {
+    return  mService->flushSensor(this, mOpPackageName);
+}
+
+int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* /*data*/) {
+    if (events & ALOOPER_EVENT_HANGUP || events & ALOOPER_EVENT_ERROR) {
+        {
+            // If the Looper encounters some error, set the flag mDead, reset mWakeLockRefCount,
+            // and remove the fd from Looper. Call checkWakeLockState to know if SensorService
+            // can release the wake-lock.
+            ALOGD_IF(DEBUG_CONNECTIONS, "%p Looper error %d", this, fd);
+            Mutex::Autolock _l(mConnectionLock);
+            mDead = true;
+            mWakeLockRefCount = 0;
+            updateLooperRegistrationLocked(mService->getLooper());
+        }
+        mService->checkWakeLockState();
+        if (mDataInjectionMode) {
+            // If the Looper has encountered some error in data injection mode, reset SensorService
+            // back to normal mode.
+            mService->resetToNormalMode();
+            mDataInjectionMode = false;
+        }
+        return 1;
+    }
+
+    if (events & ALOOPER_EVENT_INPUT) {
+        unsigned char buf[sizeof(sensors_event_t)];
+        ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
+        {
+            Mutex::Autolock _l(mConnectionLock);
+            if (numBytesRead == sizeof(sensors_event_t)) {
+                if (!mDataInjectionMode) {
+                    ALOGE("Data injected in normal mode, dropping event"
+                          "package=%s uid=%d", mPackageName.string(), mUid);
+                    // Unregister call backs.
+                    return 0;
+                }
+                sensors_event_t sensor_event;
+                memcpy(&sensor_event, buf, sizeof(sensors_event_t));
+                sp<SensorInterface> si =
+                        mService->getSensorInterfaceFromHandle(sensor_event.sensor);
+                if (si == nullptr) {
+                    return 1;
+                }
+
+                SensorDevice& dev(SensorDevice::getInstance());
+                sensor_event.type = si->getSensor().getType();
+                dev.injectSensorData(&sensor_event);
+#if DEBUG_CONNECTIONS
+                ++mEventsReceived;
+#endif
+            } else if (numBytesRead == sizeof(uint32_t)) {
+                uint32_t numAcks = 0;
+                memcpy(&numAcks, buf, numBytesRead);
+                // Sanity check to ensure  there are no read errors in recv, numAcks is always
+                // within the range and not zero. If any of the above don't hold reset
+                // mWakeLockRefCount to zero.
+                if (numAcks > 0 && numAcks < mWakeLockRefCount) {
+                    mWakeLockRefCount -= numAcks;
+                } else {
+                    mWakeLockRefCount = 0;
+                }
+#if DEBUG_CONNECTIONS
+                mTotalAcksReceived += numAcks;
+#endif
+           } else {
+               // Read error, reset wakelock refcount.
+               mWakeLockRefCount = 0;
+           }
+        }
+        // Check if wakelock can be released by sensorservice. mConnectionLock needs to be released
+        // here as checkWakeLockState() will need it.
+        if (mWakeLockRefCount == 0) {
+            mService->checkWakeLockState();
+        }
+        // continue getting callbacks.
+        return 1;
+    }
+
+    if (events & ALOOPER_EVENT_OUTPUT) {
+        // send sensor data that is stored in mEventCache for this connection.
+        mService->sendEventsFromCache(this);
+    }
+    return 1;
+}
+
+int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const {
+    size_t fifoWakeUpSensors = 0;
+    size_t fifoNonWakeUpSensors = 0;
+    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
+        sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(mSensorInfo.keyAt(i));
+        if (si == nullptr) {
+            continue;
+        }
+        const Sensor& sensor = si->getSensor();
+        if (sensor.getFifoReservedEventCount() == sensor.getFifoMaxEventCount()) {
+            // Each sensor has a reserved fifo. Sum up the fifo sizes for all wake up sensors and
+            // non wake_up sensors.
+            if (sensor.isWakeUpSensor()) {
+                fifoWakeUpSensors += sensor.getFifoReservedEventCount();
+            } else {
+                fifoNonWakeUpSensors += sensor.getFifoReservedEventCount();
+            }
+        } else {
+            // Shared fifo. Compute the max of the fifo sizes for wake_up and non_wake up sensors.
+            if (sensor.isWakeUpSensor()) {
+                fifoWakeUpSensors = fifoWakeUpSensors > sensor.getFifoMaxEventCount() ?
+                                          fifoWakeUpSensors : sensor.getFifoMaxEventCount();
+
+            } else {
+                fifoNonWakeUpSensors = fifoNonWakeUpSensors > sensor.getFifoMaxEventCount() ?
+                                          fifoNonWakeUpSensors : sensor.getFifoMaxEventCount();
+
+            }
+        }
+   }
+   if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) {
+       // It is extremely unlikely that there is a write failure in non batch mode. Return a cache
+       // size that is equal to that of the batch mode.
+       // ALOGW("Write failure in non-batch mode");
+       return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t);
+   }
+   return fifoWakeUpSensors + fifoNonWakeUpSensors;
+}
+
+} // namespace android
+
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
new file mode 100644
index 0000000..b796cc0
--- /dev/null
+++ b/services/sensorservice/SensorEventConnection.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_EVENT_CONNECTION_H
+#define ANDROID_SENSOR_EVENT_CONNECTION_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <utils/KeyedVector.h>
+#include <utils/threads.h>
+#include <utils/AndroidThreads.h>
+#include <utils/RefBase.h>
+#include <utils/Looper.h>
+#include <utils/String8.h>
+
+#include <binder/BinderService.h>
+
+#include <gui/Sensor.h>
+#include <gui/BitTube.h>
+#include <gui/ISensorServer.h>
+#include <gui/ISensorEventConnection.h>
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+class SensorService::SensorEventConnection:
+    public BnSensorEventConnection, public LooperCallback {
+
+    friend class SensorService;
+
+public:
+    SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
+                          bool isDataInjectionMode, const String16& opPackageName);
+
+    status_t sendEvents(sensors_event_t const* buffer, size_t count, sensors_event_t* scratch,
+                        SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
+    bool hasSensor(int32_t handle) const;
+    bool hasAnySensor() const;
+    bool hasOneShotSensors() const;
+    bool addSensor(int32_t handle);
+    bool removeSensor(int32_t handle);
+    void setFirstFlushPending(int32_t handle, bool value);
+    void dump(String8& result);
+    bool needsWakeLock();
+    void resetWakeLockRefCount();
+    String8 getPackageName() const;
+
+    uid_t getUid() const { return mUid; }
+
+private:
+    virtual ~SensorEventConnection();
+    virtual void onFirstRef();
+    virtual sp<BitTube> getSensorChannel() const;
+    virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
+                                   nsecs_t maxBatchReportLatencyNs, int reservedFlags);
+    virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
+    virtual status_t flush();
+    // Count the number of flush complete events which are about to be dropped in the buffer.
+    // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be sent
+    // separately before the next batch of events.
+    void countFlushCompleteEventsLocked(sensors_event_t const* scratch, int numEventsDropped);
+
+    // Check if there are any wake up events in the buffer. If yes, return the index of the first
+    // wake_up sensor event in the buffer else return -1.  This wake_up sensor event will have the
+    // flag WAKE_UP_SENSOR_EVENT_NEEDS_ACK set. Exactly one event per packet will have the wake_up
+    // flag set. SOCK_SEQPACKET ensures that either the entire packet is read or dropped.
+    int findWakeUpSensorEventLocked(sensors_event_t const* scratch, int count);
+
+    // Send pending flush_complete events. There may have been flush_complete_events that are
+    // dropped which need to be sent separately before other events. On older HALs (1_0) this method
+    // emulates the behavior of flush().
+    void sendPendingFlushEventsLocked();
+
+    // Writes events from mEventCache to the socket.
+    void writeToSocketFromCache();
+
+    // Compute the approximate cache size from the FIFO sizes of various sensors registered for this
+    // connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be shared
+    // amongst wake-up sensors and non-wake up sensors.
+    int computeMaxCacheSizeLocked() const;
+
+    // When more sensors register, the maximum cache size desired may change.  Compute max cache
+    // size, reallocate memory and copy over events from the older cache.
+    void reAllocateCacheLocked(sensors_event_t const* scratch, int count);
+
+    // LooperCallback method. If there is data to read on this fd, it is an ack from the app that it
+    // has read events from a wake up sensor, decrement mWakeLockRefCount.  If this fd is available
+    // for writing send the data from the cache.
+    virtual int handleEvent(int fd, int events, void* data);
+
+    // Increment mPendingFlushEventsToSend for the given sensor handle.
+    void incrementPendingFlushCount(int32_t handle);
+
+    // Add or remove the file descriptor associated with the BitTube to the looper. If mDead is set
+    // to true or there are no more sensors for this connection, the file descriptor is removed if
+    // it has been previously added to the Looper. Depending on the state of the connection FD may
+    // be added to the Looper. The flags to set are determined by the internal state of the
+    // connection. FDs are added to the looper when wake-up sensors are registered (to poll for
+    // acknowledgements) and when write fails on the socket when there are too many error and the
+    // other end hangs up or when this client unregisters for this connection.
+    void updateLooperRegistration(const sp<Looper>& looper); void
+            updateLooperRegistrationLocked(const sp<Looper>& looper);
+
+    sp<SensorService> const mService;
+    sp<BitTube> mChannel;
+    uid_t mUid;
+    mutable Mutex mConnectionLock;
+    // Number of events from wake up sensors which are still pending and haven't been delivered to
+    // the corresponding application. It is incremented by one unit for each write to the socket.
+    uint32_t mWakeLockRefCount;
+
+    // If this flag is set to true, it means that the file descriptor associated with the BitTube
+    // has been added to the Looper in SensorService. This flag is typically set when this
+    // connection has wake-up sensors associated with it or when write has failed on this connection
+    // and we're storing some events in the cache.
+    bool mHasLooperCallbacks;
+    // If there are any errors associated with the Looper this flag is set to true and
+    // mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if this
+    // flag is set.
+    bool mDead;
+
+    bool mDataInjectionMode;
+    struct FlushInfo {
+        // The number of flush complete events dropped for this sensor is stored here.  They are
+        // sent separately before the next batch of events.
+        int mPendingFlushEventsToSend;
+
+        // Every activate is preceded by a flush. Only after the first flush complete is received,
+        // the events for the sensor are sent on that *connection*.
+        bool mFirstFlushPending;
+
+        FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
+    };
+    // protected by SensorService::mLock. Key for this vector is the sensor handle.
+    KeyedVector<int, FlushInfo> mSensorInfo;
+
+    sensors_event_t *mEventCache;
+    int mCacheSize, mMaxCacheSize;
+    String8 mPackageName;
+    const String16 mOpPackageName;
+#if DEBUG_CONNECTIONS
+    int mEventsReceived, mEventsSent, mEventsSentFromCache;
+    int mTotalAcksNeeded, mTotalAcksReceived;
+#endif
+
+};
+
+} // namepsace android
+
+#endif // ANDROID_SENSOR_EVENT_CONNECTION_H
+
diff --git a/services/sensorservice/SensorFusion.cpp b/services/sensorservice/SensorFusion.cpp
index 6d93009..9863f62 100644
--- a/services/sensorservice/SensorFusion.cpp
+++ b/services/sensorservice/SensorFusion.cpp
@@ -25,11 +25,17 @@
 
 SensorFusion::SensorFusion()
     : mSensorDevice(SensorDevice::getInstance()),
-      mEnabled(false), mGyroTime(0)
+      mAttitude(mAttitudes[FUSION_9AXIS]),
+      mGyroTime(0), mAccTime(0)
 {
     sensor_t const* list;
     Sensor uncalibratedGyro;
     ssize_t count = mSensorDevice.getSensorList(&list);
+
+    mEnabled[FUSION_9AXIS] = false;
+    mEnabled[FUSION_NOMAG] = false;
+    mEnabled[FUSION_NOGYRO] = false;
+
     if (count > 0) {
         for (size_t i=0 ; i<size_t(count) ; i++) {
             if (list[i].type == SENSOR_TYPE_ACCELEROMETER) {
@@ -55,81 +61,121 @@
         // and power/cpu usage.
         mEstimatedGyroRate = 200;
         mTargetDelayNs = 1000000000LL/mEstimatedGyroRate;
-        mFusion.init();
+
+        for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+            mFusions[i].init(i);
+        }
     }
 }
 
 void SensorFusion::process(const sensors_event_t& event) {
+
     if (event.type == mGyro.getType()) {
-        if (mGyroTime != 0) {
-            const float dT = (event.timestamp - mGyroTime) / 1000000000.0f;
-            mFusion.handleGyro(vec3_t(event.data), dT);
+        float dT;
+        if ( event.timestamp - mGyroTime> 0 &&
+             event.timestamp - mGyroTime< (int64_t)(5e7) ) { //0.05sec
+
+            dT = (event.timestamp - mGyroTime) / 1000000000.0f;
             // here we estimate the gyro rate (useful for debugging)
             const float freq = 1 / dT;
             if (freq >= 100 && freq<1000) { // filter values obviously wrong
                 const float alpha = 1 / (1 + dT); // 1s time-constant
                 mEstimatedGyroRate = freq + (mEstimatedGyroRate - freq)*alpha;
             }
+
+            const vec3_t gyro(event.data);
+            for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+                if (mEnabled[i]) {
+                    // fusion in no gyro mode will ignore
+                    mFusions[i].handleGyro(gyro, dT);
+                }
+            }
         }
         mGyroTime = event.timestamp;
     } else if (event.type == SENSOR_TYPE_MAGNETIC_FIELD) {
         const vec3_t mag(event.data);
-        mFusion.handleMag(mag);
+        for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+            if (mEnabled[i]) {
+                mFusions[i].handleMag(mag);// fusion in no mag mode will ignore
+            }
+        }
     } else if (event.type == SENSOR_TYPE_ACCELEROMETER) {
-        const vec3_t acc(event.data);
-        mFusion.handleAcc(acc);
-        mAttitude = mFusion.getAttitude();
+        float dT;
+        if ( event.timestamp - mAccTime> 0 &&
+             event.timestamp - mAccTime< (int64_t)(1e8) ) { //0.1sec
+            dT = (event.timestamp - mAccTime) / 1000000000.0f;
+
+            const vec3_t acc(event.data);
+            for (int i = 0; i<NUM_FUSION_MODE; ++i) {
+                if (mEnabled[i]) {
+                    mFusions[i].handleAcc(acc, dT);
+                    mAttitudes[i] = mFusions[i].getAttitude();
+                }
+            }
+        }
+        mAccTime = event.timestamp;
     }
 }
 
 template <typename T> inline T min(T a, T b) { return a<b ? a : b; }
 template <typename T> inline T max(T a, T b) { return a>b ? a : b; }
 
-status_t SensorFusion::activate(void* ident, bool enabled) {
+status_t SensorFusion::activate(int mode, void* ident, bool enabled) {
 
     ALOGD_IF(DEBUG_CONNECTIONS,
-            "SensorFusion::activate(ident=%p, enabled=%d)",
-            ident, enabled);
+            "SensorFusion::activate(mode=%d, ident=%p, enabled=%d)",
+            mode, ident, enabled);
 
-    const ssize_t idx = mClients.indexOf(ident);
+    const ssize_t idx = mClients[mode].indexOf(ident);
     if (enabled) {
         if (idx < 0) {
-            mClients.add(ident);
+            mClients[mode].add(ident);
         }
     } else {
         if (idx >= 0) {
-            mClients.removeItemsAt(idx);
+            mClients[mode].removeItemsAt(idx);
+        }
+    }
+
+    const bool newState = mClients[mode].size() != 0;
+    if (newState != mEnabled[mode]) {
+        mEnabled[mode] = newState;
+        if (newState) {
+            mFusions[mode].init(mode);
         }
     }
 
     mSensorDevice.activate(ident, mAcc.getHandle(), enabled);
-    mSensorDevice.activate(ident, mMag.getHandle(), enabled);
-    mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
+    if (mode != FUSION_NOMAG) {
+        mSensorDevice.activate(ident, mMag.getHandle(), enabled);
+    }
+    if (mode != FUSION_NOGYRO) {
+        mSensorDevice.activate(ident, mGyro.getHandle(), enabled);
+    }
 
-    const bool newState = mClients.size() != 0;
-    if (newState != mEnabled) {
-        mEnabled = newState;
-        if (newState) {
-            mFusion.init();
-            mGyroTime = 0;
-        }
+    return NO_ERROR;
+}
+
+status_t SensorFusion::setDelay(int mode, void* ident, int64_t ns) {
+    // Call batch with timeout zero instead of setDelay().
+    if (ns > (int64_t)5e7) {
+        ns = (int64_t)(5e7);
+    }
+    mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
+    if (mode != FUSION_NOMAG) {
+        mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
+    }
+    if (mode != FUSION_NOGYRO) {
+        mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
     }
     return NO_ERROR;
 }
 
-status_t SensorFusion::setDelay(void* ident, int64_t ns) {
-    // Call batch with timeout zero instead of setDelay().
-    mSensorDevice.batch(ident, mAcc.getHandle(), 0, ns, 0);
-    mSensorDevice.batch(ident, mMag.getHandle(), 0, ms2ns(20), 0);
-    mSensorDevice.batch(ident, mGyro.getHandle(), 0, mTargetDelayNs, 0);
-    return NO_ERROR;
-}
 
-
-float SensorFusion::getPowerUsage() const {
+float SensorFusion::getPowerUsage(int mode) const {
     float power =   mAcc.getPowerUsage() +
-                    mMag.getPowerUsage() +
-                    mGyro.getPowerUsage();
+                    ((mode != FUSION_NOMAG) ? mMag.getPowerUsage() : 0) +
+                    ((mode != FUSION_NOGYRO) ? mGyro.getPowerUsage() : 0);
     return power;
 }
 
@@ -138,21 +184,55 @@
 }
 
 void SensorFusion::dump(String8& result) {
-    const Fusion& fusion(mFusion);
+    const Fusion& fusion_9axis(mFusions[FUSION_9AXIS]);
     result.appendFormat("9-axis fusion %s (%zd clients), gyro-rate=%7.2fHz, "
             "q=< %g, %g, %g, %g > (%g), "
             "b=< %g, %g, %g >\n",
-            mEnabled ? "enabled" : "disabled",
-            mClients.size(),
+            mEnabled[FUSION_9AXIS] ? "enabled" : "disabled",
+            mClients[FUSION_9AXIS].size(),
             mEstimatedGyroRate,
-            fusion.getAttitude().x,
-            fusion.getAttitude().y,
-            fusion.getAttitude().z,
-            fusion.getAttitude().w,
-            length(fusion.getAttitude()),
-            fusion.getBias().x,
-            fusion.getBias().y,
-            fusion.getBias().z);
+            fusion_9axis.getAttitude().x,
+            fusion_9axis.getAttitude().y,
+            fusion_9axis.getAttitude().z,
+            fusion_9axis.getAttitude().w,
+            length(fusion_9axis.getAttitude()),
+            fusion_9axis.getBias().x,
+            fusion_9axis.getBias().y,
+            fusion_9axis.getBias().z);
+
+    const Fusion& fusion_nomag(mFusions[FUSION_NOMAG]);
+    result.appendFormat("game fusion(no mag) %s (%zd clients), "
+            "gyro-rate=%7.2fHz, "
+            "q=< %g, %g, %g, %g > (%g), "
+            "b=< %g, %g, %g >\n",
+            mEnabled[FUSION_NOMAG] ? "enabled" : "disabled",
+            mClients[FUSION_NOMAG].size(),
+            mEstimatedGyroRate,
+            fusion_nomag.getAttitude().x,
+            fusion_nomag.getAttitude().y,
+            fusion_nomag.getAttitude().z,
+            fusion_nomag.getAttitude().w,
+            length(fusion_nomag.getAttitude()),
+            fusion_nomag.getBias().x,
+            fusion_nomag.getBias().y,
+            fusion_nomag.getBias().z);
+
+    const Fusion& fusion_nogyro(mFusions[FUSION_NOGYRO]);
+    result.appendFormat("geomag fusion (no gyro) %s (%zd clients), "
+            "gyro-rate=%7.2fHz, "
+            "q=< %g, %g, %g, %g > (%g), "
+            "b=< %g, %g, %g >\n",
+            mEnabled[FUSION_NOGYRO] ? "enabled" : "disabled",
+            mClients[FUSION_NOGYRO].size(),
+            mEstimatedGyroRate,
+            fusion_nogyro.getAttitude().x,
+            fusion_nogyro.getAttitude().y,
+            fusion_nogyro.getAttitude().z,
+            fusion_nogyro.getAttitude().w,
+            length(fusion_nogyro.getAttitude()),
+            fusion_nogyro.getBias().x,
+            fusion_nogyro.getBias().y,
+            fusion_nogyro.getBias().z);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorFusion.h b/services/sensorservice/SensorFusion.h
index 432adbc..ad636d5 100644
--- a/services/sensorservice/SensorFusion.h
+++ b/services/sensorservice/SensorFusion.h
@@ -42,30 +42,52 @@
     Sensor mAcc;
     Sensor mMag;
     Sensor mGyro;
-    Fusion mFusion;
-    bool mEnabled;
+
+    Fusion mFusions[NUM_FUSION_MODE]; // normal, no_mag, no_gyro
+
+    bool mEnabled[NUM_FUSION_MODE];
+
+    vec4_t &mAttitude;
+    vec4_t mAttitudes[NUM_FUSION_MODE];
+
+    SortedVector<void*> mClients[3];
+
     float mEstimatedGyroRate;
     nsecs_t mTargetDelayNs;
+
     nsecs_t mGyroTime;
-    vec4_t mAttitude;
-    SortedVector<void*> mClients;
+    nsecs_t mAccTime;
 
     SensorFusion();
 
 public:
     void process(const sensors_event_t& event);
 
-    bool isEnabled() const { return mEnabled; }
-    bool hasEstimate() const { return mFusion.hasEstimate(); }
-    mat33_t getRotationMatrix() const { return mFusion.getRotationMatrix(); }
-    vec4_t getAttitude() const { return mAttitude; }
-    vec3_t getGyroBias() const { return mFusion.getBias(); }
+    bool isEnabled() const {
+        return mEnabled[FUSION_9AXIS] ||
+                mEnabled[FUSION_NOMAG] ||
+                mEnabled[FUSION_NOGYRO];
+    }
+
+    bool hasEstimate(int mode = FUSION_9AXIS) const {
+        return mFusions[mode].hasEstimate();
+    }
+
+    mat33_t getRotationMatrix(int mode = FUSION_9AXIS) const {
+        return mFusions[mode].getRotationMatrix();
+    }
+
+    vec4_t getAttitude(int mode = FUSION_9AXIS) const {
+        return mAttitudes[mode];
+    }
+
+    vec3_t getGyroBias() const { return mFusions[FUSION_9AXIS].getBias(); }
     float getEstimatedRate() const { return mEstimatedGyroRate; }
 
-    status_t activate(void* ident, bool enabled);
-    status_t setDelay(void* ident, int64_t ns);
+    status_t activate(int mode, void* ident, bool enabled);
+    status_t setDelay(int mode, void* ident, int64_t ns);
 
-    float getPowerUsage() const;
+    float getPowerUsage(int mode=FUSION_9AXIS) const;
     int32_t getMinDelay() const;
 
     void dump(String8& result);
diff --git a/services/sensorservice/SensorInterface.cpp b/services/sensorservice/SensorInterface.cpp
index 970220b..73a6db5 100644
--- a/services/sensorservice/SensorInterface.cpp
+++ b/services/sensorservice/SensorInterface.cpp
@@ -14,24 +14,39 @@
  * limitations under the License.
  */
 
+#include "SensorInterface.h"
+#include "SensorDevice.h"
+#include "SensorFusion.h"
+
 #include <stdint.h>
 #include <sys/types.h>
 
-#include "SensorInterface.h"
-
 namespace android {
 // ---------------------------------------------------------------------------
 
-SensorInterface::~SensorInterface()
-{
+namespace {
+const sensor_t DUMMY_SENSOR = {
+        .name = "", .vendor = "", .stringType = "", .requiredPermission = ""};
+} //unnamed namespace
+
+BaseSensor::BaseSensor(const sensor_t& sensor) :
+        mSensorDevice(SensorDevice::getInstance()),
+        mSensor(&sensor, mSensorDevice.getHalDeviceVersion()) {
+}
+
+BaseSensor::BaseSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]) :
+        mSensorDevice(SensorDevice::getInstance()),
+        mSensor(sensor, Sensor::uuid_t(uuid), mSensorDevice.getHalDeviceVersion()) {
 }
 
 // ---------------------------------------------------------------------------
 
-HardwareSensor::HardwareSensor(const sensor_t& sensor)
-    : mSensorDevice(SensorDevice::getInstance()),
-      mSensor(&sensor, mSensorDevice.getHalDeviceVersion())
-{
+HardwareSensor::HardwareSensor(const sensor_t& sensor):
+        BaseSensor(sensor) {
+}
+
+HardwareSensor::HardwareSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]):
+        BaseSensor(sensor, uuid) {
 }
 
 HardwareSensor::~HardwareSensor() {
@@ -65,10 +80,9 @@
     mSensorDevice.autoDisable(ident, handle);
 }
 
-Sensor HardwareSensor::getSensor() const {
-    return mSensor;
+VirtualSensor::VirtualSensor() :
+        BaseSensor(DUMMY_SENSOR), mSensorFusion(SensorFusion::getInstance()) {
 }
 
-
 // ---------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/sensorservice/SensorInterface.h b/services/sensorservice/SensorInterface.h
index 3e76377..dafcf2d 100644
--- a/services/sensorservice/SensorInterface.h
+++ b/services/sensorservice/SensorInterface.h
@@ -17,69 +17,87 @@
 #ifndef ANDROID_SENSOR_INTERFACE_H
 #define ANDROID_SENSOR_INTERFACE_H
 
-#include <stdint.h>
-#include <sys/types.h>
-
 #include <gui/Sensor.h>
-
-#include "SensorDevice.h"
+#include <utils/RefBase.h>
 
 // ---------------------------------------------------------------------------
 
 namespace android {
 // ---------------------------------------------------------------------------
+class SensorDevice;
+class SensorFusion;
 
-class SensorInterface {
+class SensorInterface : public VirtualLightRefBase {
 public:
-    virtual ~SensorInterface();
+    virtual ~SensorInterface() {}
 
-    virtual bool process(sensors_event_t* outEvent,
-            const sensors_event_t& event) = 0;
+    virtual bool process(sensors_event_t* outEvent, const sensors_event_t& event) = 0;
 
     virtual status_t activate(void* ident, bool enabled) = 0;
     virtual status_t setDelay(void* ident, int handle, int64_t ns) = 0;
+    virtual status_t batch(void* ident, int handle, int /*flags*/, int64_t samplingPeriodNs,
+                           int64_t maxBatchReportLatencyNs) = 0;
+
+    virtual status_t flush(void* /*ident*/, int /*handle*/) = 0;
+
+    virtual const Sensor& getSensor() const = 0;
+    virtual bool isVirtual() const = 0;
+    virtual void autoDisable(void* /*ident*/, int /*handle*/) = 0;
+};
+
+class BaseSensor : public SensorInterface {
+public:
+    BaseSensor(const sensor_t& sensor);
+    BaseSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]);
 
     // Not all sensors need to support batching.
-    virtual status_t batch(void* ident, int handle, int /*flags*/, int64_t samplingPeriodNs,
-                           int64_t maxBatchReportLatencyNs) {
+    virtual status_t batch(void* ident, int handle, int, int64_t samplingPeriodNs,
+                           int64_t maxBatchReportLatencyNs) override {
         if (maxBatchReportLatencyNs == 0) {
             return setDelay(ident, handle, samplingPeriodNs);
         }
         return -EINVAL;
     }
 
-    virtual status_t flush(void* /*ident*/, int /*handle*/) {
+    virtual status_t flush(void* /*ident*/, int /*handle*/) override {
         return -EINVAL;
     }
 
-    virtual Sensor getSensor() const = 0;
-    virtual bool isVirtual() const = 0;
-    virtual void autoDisable(void* /*ident*/, int /*handle*/) { }
+    virtual const Sensor& getSensor() const override { return mSensor; }
+    virtual void autoDisable(void* /*ident*/, int /*handle*/) override { }
+protected:
+    SensorDevice& mSensorDevice;
+    Sensor mSensor;
 };
 
 // ---------------------------------------------------------------------------
 
-class HardwareSensor : public SensorInterface
-{
-    SensorDevice& mSensorDevice;
-    Sensor mSensor;
-
+class HardwareSensor : public BaseSensor {
 public:
     HardwareSensor(const sensor_t& sensor);
+    HardwareSensor(const sensor_t& sensor, const uint8_t (&uuid)[16]);
 
     virtual ~HardwareSensor();
 
     virtual bool process(sensors_event_t* outEvent,
             const sensors_event_t& event);
 
-    virtual status_t activate(void* ident, bool enabled);
+    virtual status_t activate(void* ident, bool enabled) override;
     virtual status_t batch(void* ident, int handle, int flags, int64_t samplingPeriodNs,
-                           int64_t maxBatchReportLatencyNs);
-    virtual status_t setDelay(void* ident, int handle, int64_t ns);
-    virtual status_t flush(void* ident, int handle);
-    virtual Sensor getSensor() const;
-    virtual bool isVirtual() const { return false; }
-    virtual void autoDisable(void *ident, int handle);
+                           int64_t maxBatchReportLatencyNs) override;
+    virtual status_t setDelay(void* ident, int handle, int64_t ns) override;
+    virtual status_t flush(void* ident, int handle) override;
+    virtual bool isVirtual() const override { return false; }
+    virtual void autoDisable(void *ident, int handle) override;
+};
+
+class VirtualSensor : public BaseSensor
+{
+public:
+    VirtualSensor();
+    virtual bool isVirtual() const override { return true; }
+protected:
+    SensorFusion& mSensorFusion;
 };
 
 
diff --git a/services/sensorservice/SensorList.cpp b/services/sensorservice/SensorList.cpp
new file mode 100644
index 0000000..f6d3d94
--- /dev/null
+++ b/services/sensorservice/SensorList.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 "SensorList.h"
+
+#include <hardware/sensors.h>
+#include <utils/String8.h>
+
+#include <cinttypes>
+
+namespace android {
+namespace SensorServiceUtil {
+
+const Sensor SensorList::mNonSensor = Sensor("unknown");
+
+bool SensorList::add(
+        int handle, SensorInterface* si, bool isForDebug, bool isVirtual) {
+    std::lock_guard<std::mutex> lk(mLock);
+    if (handle == si->getSensor().getHandle() &&
+        mUsedHandle.insert(handle).second) {
+        // will succeed as the mUsedHandle does not have this handle
+        mHandleMap.emplace(handle, Entry(si, isForDebug, isVirtual));
+        return true;
+    }
+    // handle exist already or handle mismatch
+    return false;
+}
+
+bool SensorList::remove(int handle) {
+    std::lock_guard<std::mutex> lk(mLock);
+    auto entry = mHandleMap.find(handle);
+    if (entry != mHandleMap.end()) {
+        mHandleMap.erase(entry);
+        return true;
+    }
+    return false;
+}
+
+String8 SensorList::getName(int handle) const {
+    return getOne<String8>(
+            handle, [] (const Entry& e) -> String8 {return e.si->getSensor().getName();},
+            mNonSensor.getName());
+}
+
+sp<SensorInterface> SensorList::getInterface(int handle) const {
+    return getOne<sp<SensorInterface>>(
+            handle, [] (const Entry& e) -> sp<SensorInterface> {return e.si;}, nullptr);
+}
+
+
+bool SensorList::isNewHandle(int handle) const {
+    std::lock_guard<std::mutex> lk(mLock);
+    return mUsedHandle.find(handle) == mUsedHandle.end();
+}
+
+const Vector<Sensor> SensorList::getUserSensors() const {
+    // lock in forEachEntry
+    Vector<Sensor> sensors;
+    forEachEntry(
+            [&sensors] (const Entry& e) -> bool {
+                if (!e.isForDebug && !e.si->getSensor().isDynamicSensor()) {
+                    sensors.add(e.si->getSensor());
+                }
+                return true;
+            });
+    return sensors;
+}
+
+const Vector<Sensor> SensorList::getUserDebugSensors() const {
+    // lock in forEachEntry
+    Vector<Sensor> sensors;
+    forEachEntry(
+            [&sensors] (const Entry& e) -> bool {
+                if (!e.si->getSensor().isDynamicSensor()) {
+                    sensors.add(e.si->getSensor());
+                }
+                return true;
+            });
+    return sensors;
+}
+
+const Vector<Sensor> SensorList::getDynamicSensors() const {
+    // lock in forEachEntry
+    Vector<Sensor> sensors;
+    forEachEntry(
+            [&sensors] (const Entry& e) -> bool {
+                if (!e.isForDebug && e.si->getSensor().isDynamicSensor()) {
+                    sensors.add(e.si->getSensor());
+                }
+                return true;
+            });
+    return sensors;
+}
+
+const Vector<Sensor> SensorList::getVirtualSensors() const {
+    // lock in forEachEntry
+    Vector<Sensor> sensors;
+    forEachEntry(
+            [&sensors] (const Entry& e) -> bool {
+                if (e.isVirtual) {
+                    sensors.add(e.si->getSensor());
+                }
+                return true;
+            });
+    return sensors;
+}
+
+std::string SensorList::dump() const {
+    String8 result;
+
+    forEachSensor([&result] (const Sensor& s) -> bool {
+            result.appendFormat(
+                    "%#010x) %-25s | %-15s | ver: %" PRId32 " | type: %20s(%" PRId32
+                        ") | perm: %s\n\t",
+                    s.getHandle(),
+                    s.getName().string(),
+                    s.getVendor().string(),
+                    s.getVersion(),
+                    s.getStringType().string(),
+                    s.getType(),
+                    s.getRequiredPermission().size() ? s.getRequiredPermission().string() : "n/a");
+
+            const int reportingMode = s.getReportingMode();
+            if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
+                result.append(" continuous | ");
+            } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
+                result.append(" on-change | ");
+            } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
+                result.append(" one-shot | ");
+            } else if (reportingMode == AREPORTING_MODE_SPECIAL_TRIGGER) {
+                result.append(" special-trigger | ");
+            } else {
+                result.append(" unknown-mode | ");
+            }
+
+            if (s.getMaxDelay() > 0) {
+                result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
+            } else {
+                result.appendFormat("maxDelay=%" PRId32 "us | ", s.getMaxDelay());
+            }
+
+            if (s.getMinDelay() > 0) {
+                result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
+            } else {
+                result.appendFormat("minDelay=%" PRId32 "us | ", s.getMinDelay());
+            }
+
+            if (s.getFifoMaxEventCount() > 0) {
+                result.appendFormat("FIFO (max,reserved) = (%" PRIu32 ", %" PRIu32 ") events | ",
+                        s.getFifoMaxEventCount(),
+                        s.getFifoReservedEventCount());
+            } else {
+                result.append("no batching | ");
+            }
+
+            if (s.isWakeUpSensor()) {
+                result.appendFormat("wakeUp | ");
+            } else {
+                result.appendFormat("non-wakeUp | ");
+            }
+
+            if (s.isDynamicSensor()) {
+                result.appendFormat("dynamic, ");
+            }
+            if (s.hasAdditionalInfo()) {
+                result.appendFormat("has-additional-info, ");
+            }
+            result.append("| ");
+
+            if (s.isDynamicSensor()) {
+                result.append("uuid: ");
+                for (uint8_t i : s.getUuid().b) {
+                    result.appendFormat("%02x", i);
+                }
+            }
+            result.append("\n");
+            return true;
+        });
+    return std::string(result.string());
+}
+
+SensorList::~SensorList() {
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
diff --git a/services/sensorservice/SensorList.h b/services/sensorservice/SensorList.h
new file mode 100644
index 0000000..8209d96
--- /dev/null
+++ b/services/sensorservice/SensorList.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
+#define ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
+
+#include "SensorInterface.h"
+#include "SensorServiceUtils.h"
+
+#include <gui/Sensor.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+#include <map>
+#include <mutex>
+#include <unordered_set>
+#include <vector>
+
+namespace android {
+class SensorInterface;
+
+namespace SensorServiceUtil {
+
+class SensorList : public Dumpable {
+public:
+    // After SensorInterface * is added into SensorList, it can be assumed that SensorList own the
+    // object it pointed to and the object should not be released elsewhere.
+    bool add(int handle, SensorInterface* si, bool isForDebug = false, bool isVirtual = false);
+
+    // After a handle is removed, the object that SensorInterface * pointing to may get deleted if
+    // no more sp<> of the same object exist.
+    bool remove(int handle);
+
+    inline bool hasAnySensor() const { return mHandleMap.size() > 0;}
+
+    //helper functions
+    const Vector<Sensor> getUserSensors() const;
+    const Vector<Sensor> getUserDebugSensors() const;
+    const Vector<Sensor> getDynamicSensors() const;
+    const Vector<Sensor> getVirtualSensors() const;
+
+    String8 getName(int handle) const;
+    sp<SensorInterface> getInterface(int handle) const;
+    bool isNewHandle(int handle) const;
+
+    // Iterate through Sensor in sensor list and perform operation f on each Sensor object.
+    //
+    // TF is a function with the signature:
+    //    bool f(const Sensor &);
+    // A return value of 'false' stops the iteration immediately.
+    //
+    // Note: in the function f, it is illegal to make calls to member functions of the same
+    // SensorList object on which forEachSensor is invoked.
+    template <typename TF>
+    void forEachSensor(const TF& f) const;
+
+    const Sensor& getNonSensor() const { return mNonSensor;}
+
+    // Dumpable interface
+    virtual std::string dump() const override;
+
+    virtual ~SensorList();
+private:
+    struct Entry {
+        sp<SensorInterface> si;
+        const bool isForDebug;
+        const bool isVirtual;
+        Entry(SensorInterface* si_, bool debug_, bool virtual_) :
+            si(si_), isForDebug(debug_), isVirtual(virtual_) {
+        }
+    };
+
+    const static Sensor mNonSensor; //.getName() == "unknown",
+
+    // Iterate through Entry in sensor list and perform operation f on each Entry.
+    //
+    // TF is a function with the signature:
+    //    bool f(const Entry &);
+    // A return value of 'false' stops the iteration over entries immediately.
+    //
+    // Note: in the function being passed in, it is illegal to make calls to member functions of the
+    // same SensorList object on which forEachSensor is invoked.
+    template <typename TF>
+    void forEachEntry(const TF& f) const;
+
+    template <typename T, typename TF>
+    T getOne(int handle, const TF& accessor, T def = T()) const;
+
+    mutable std::mutex mLock;
+    std::map<int, Entry> mHandleMap;
+    std::unordered_set<int> mUsedHandle;
+};
+
+template <typename TF>
+void SensorList::forEachSensor(const TF& f) const {
+    // lock happens in forEachEntry
+    forEachEntry([&f] (const Entry& e) -> bool { return f(e.si->getSensor());});
+}
+
+template <typename TF>
+void SensorList::forEachEntry(const TF& f) const {
+    std::lock_guard<std::mutex> lk(mLock);
+
+    for (auto&& i : mHandleMap) {
+        if (!f(i.second)){
+            break;
+        }
+    }
+}
+
+template <typename T, typename TF>
+T SensorList::getOne(int handle, const TF& accessor, T def) const {
+    std::lock_guard<std::mutex> lk(mLock);
+    auto i = mHandleMap.find(handle);
+    if (i != mHandleMap.end()) {
+        return accessor(i->second);
+    } else {
+        return def;
+    }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL_SENSOR_LIST_H
diff --git a/services/sensorservice/SensorRecord.cpp b/services/sensorservice/SensorRecord.cpp
new file mode 100644
index 0000000..644cfb0
--- /dev/null
+++ b/services/sensorservice/SensorRecord.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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 "SensorRecord.h"
+
+#include "SensorEventConnection.h"
+
+namespace android {
+
+SensorService::SensorRecord::SensorRecord(
+        const sp<SensorEventConnection>& connection)
+{
+    mConnections.add(connection);
+}
+
+bool SensorService::SensorRecord::addConnection(
+        const sp<SensorEventConnection>& connection)
+{
+    if (mConnections.indexOf(connection) < 0) {
+        mConnections.add(connection);
+        return true;
+    }
+    return false;
+}
+
+bool SensorService::SensorRecord::removeConnection(
+        const wp<SensorEventConnection>& connection)
+{
+    ssize_t index = mConnections.indexOf(connection);
+    if (index >= 0) {
+        mConnections.removeItemsAt(index, 1);
+    }
+    // Remove this connections from the queue of flush() calls made on this sensor.
+    for (Vector< wp<SensorEventConnection> >::iterator it = mPendingFlushConnections.begin();
+            it != mPendingFlushConnections.end(); ) {
+        if (it->unsafe_get() == connection.unsafe_get()) {
+            it = mPendingFlushConnections.erase(it);
+        } else {
+            ++it;
+        }
+    }
+    return mConnections.size() ? false : true;
+}
+
+void SensorService::SensorRecord::addPendingFlushConnection(
+        const sp<SensorEventConnection>& connection) {
+    mPendingFlushConnections.add(connection);
+}
+
+void SensorService::SensorRecord::removeFirstPendingFlushConnection() {
+    if (mPendingFlushConnections.size() > 0) {
+        mPendingFlushConnections.removeAt(0);
+    }
+}
+
+SensorService::SensorEventConnection *
+        SensorService::SensorRecord::getFirstPendingFlushConnection() {
+    if (mPendingFlushConnections.size() > 0) {
+        return mPendingFlushConnections[0].unsafe_get();
+    }
+    return NULL;
+}
+
+void SensorService::SensorRecord::clearAllPendingFlushConnections() {
+    mPendingFlushConnections.clear();
+}
+
+} // namespace android
diff --git a/services/sensorservice/SensorRecord.h b/services/sensorservice/SensorRecord.h
new file mode 100644
index 0000000..29b970d
--- /dev/null
+++ b/services/sensorservice/SensorRecord.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_RECORD_H
+#define ANDROID_SENSOR_RECORD_H
+
+#include "SensorService.h"
+
+namespace android {
+
+class SensorService;
+
+class SensorService::SensorRecord {
+public:
+    SensorRecord(const sp<SensorEventConnection>& connection);
+    bool addConnection(const sp<SensorEventConnection>& connection);
+    bool removeConnection(const wp<SensorEventConnection>& connection);
+    size_t getNumConnections() const { return mConnections.size(); }
+
+    void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
+    void removeFirstPendingFlushConnection();
+    SensorEventConnection * getFirstPendingFlushConnection();
+    void clearAllPendingFlushConnections();
+private:
+    SortedVector< wp<SensorEventConnection> > mConnections;
+    // A queue of all flush() calls made on this sensor. Flush complete events
+    // will be sent in this order.
+    Vector< wp<SensorEventConnection> > mPendingFlushConnections;
+};
+
+}
+
+#endif // ANDROID_SENSOR_RECORD_H
diff --git a/services/sensorservice/SensorRegistrationInfo.h b/services/sensorservice/SensorRegistrationInfo.h
new file mode 100644
index 0000000..54d815b
--- /dev/null
+++ b/services/sensorservice/SensorRegistrationInfo.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_REGISTRATION_INFO_H
+#define ANDROID_SENSOR_REGISTRATION_INFO_H
+
+namespace android {
+
+class SensorService;
+
+struct SensorService::SensorRegistrationInfo {
+    int32_t mSensorHandle;
+    String8 mPackageName;
+    bool mActivated;
+    int32_t mSamplingRateUs;
+    int32_t mMaxReportLatencyUs;
+    int32_t mHour, mMin, mSec;
+
+    SensorRegistrationInfo() : mPackageName() {
+        mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
+        mHour = mMin = mSec = INT32_MIN;
+        mActivated = false;
+    }
+
+    static bool isSentinel(const SensorRegistrationInfo& info) {
+       return (info.mHour == INT32_MIN &&
+               info.mMin == INT32_MIN &&
+               info.mSec == INT32_MIN);
+    }
+};
+
+} // namespace android;
+
+#endif // ANDROID_SENSOR_REGISTRATION_INFO_H
+
+
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 2f64558..6caa85b 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -14,30 +14,13 @@
  * limitations under the License.
  */
 
-#include <inttypes.h>
-#include <math.h>
-#include <stdint.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
 #include <cutils/properties.h>
 
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Atomic.h>
-#include <utils/Errors.h>
-#include <utils/RefBase.h>
-#include <utils/Singleton.h>
-#include <utils/String16.h>
-
 #include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
 
-#include <gui/ISensorServer.h>
-#include <gui/ISensorEventConnection.h>
 #include <gui/SensorEventQueue.h>
 
 #include <hardware/sensors.h>
@@ -50,7 +33,19 @@
 #include "OrientationSensor.h"
 #include "RotationVectorSensor.h"
 #include "SensorFusion.h"
+#include "SensorInterface.h"
+
 #include "SensorService.h"
+#include "SensorEventAckReceiver.h"
+#include "SensorEventConnection.h"
+#include "SensorRecord.h"
+#include "SensorRegistrationInfo.h"
+
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/socket.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
@@ -70,12 +65,10 @@
 
 SensorService::SensorService()
     : mInitCheck(NO_INIT), mSocketBufferSize(SOCKET_BUFFER_SIZE_NON_BATCHED),
-      mWakeLockAcquired(false)
-{
+      mWakeLockAcquired(false) {
 }
 
-void SensorService::onFirstRef()
-{
+void SensorService::onFirstRef() {
     ALOGD("nuSensorService starting...");
     SensorDevice& dev(SensorDevice::getInstance());
 
@@ -88,11 +81,13 @@
             uint32_t virtualSensorsNeeds =
                     (1<<SENSOR_TYPE_GRAVITY) |
                     (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
-                    (1<<SENSOR_TYPE_ROTATION_VECTOR);
+                    (1<<SENSOR_TYPE_ROTATION_VECTOR) |
+                    (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR) |
+                    (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR);
 
-            mLastEventSeen.setCapacity(count);
             for (ssize_t i=0 ; i<count ; i++) {
-                registerSensor( new HardwareSensor(list[i]) );
+                bool useThisSensor=true;
+
                 switch (list[i].type) {
                     case SENSOR_TYPE_ACCELEROMETER:
                         hasAccel = true;
@@ -110,64 +105,70 @@
                     case SENSOR_TYPE_GRAVITY:
                     case SENSOR_TYPE_LINEAR_ACCELERATION:
                     case SENSOR_TYPE_ROTATION_VECTOR:
-                        virtualSensorsNeeds &= ~(1<<list[i].type);
+                    case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+                    case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+                        if (IGNORE_HARDWARE_FUSION) {
+                            useThisSensor = false;
+                        } else {
+                            virtualSensorsNeeds &= ~(1<<list[i].type);
+                        }
                         break;
                 }
+                if (useThisSensor) {
+                    registerSensor( new HardwareSensor(list[i]) );
+                }
             }
 
             // it's safe to instantiate the SensorFusion object here
             // (it wants to be instantiated after h/w sensors have been
             // registered)
-            const SensorFusion& fusion(SensorFusion::getInstance());
-
-            // build the sensor list returned to users
-            mUserSensorList = mSensorList;
+            SensorFusion::getInstance();
 
             if (hasGyro && hasAccel && hasMag) {
-                Sensor aSensor;
-
                 // Add Android virtual sensors if they're not already
                 // available in the HAL
+                bool needRotationVector =
+                        (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) != 0;
 
-                aSensor = registerVirtualSensor( new RotationVectorSensor() );
-                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
-                    mUserSensorList.add(aSensor);
-                }
+                registerSensor(new RotationVectorSensor(), !needRotationVector, true);
+                registerSensor(new OrientationSensor(), !needRotationVector, true);
 
-                aSensor = registerVirtualSensor( new GravitySensor(list, count) );
-                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
-                    mUserSensorList.add(aSensor);
-                }
+                bool needLinearAcceleration =
+                        (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
 
-                aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
-                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
-                    mUserSensorList.add(aSensor);
-                }
+                registerSensor(new LinearAccelerationSensor(list, count),
+                               !needLinearAcceleration, true);
 
-                aSensor = registerVirtualSensor( new OrientationSensor() );
-                if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
-                    // if we are doing our own rotation-vector, also add
-                    // the orientation sensor and remove the HAL provided one.
-                    mUserSensorList.replaceAt(aSensor, orientationIndex);
-                }
-
-                // virtual debugging sensors are not added to mUserSensorList
-                registerVirtualSensor( new CorrectedGyroSensor(list, count) );
-                registerVirtualSensor( new GyroDriftSensor() );
+                // virtual debugging sensors are not for user
+                registerSensor( new CorrectedGyroSensor(list, count), true, true);
+                registerSensor( new GyroDriftSensor(), true, true);
             }
 
-            // debugging sensor list
-            mUserSensorListDebug = mSensorList;
+            if (hasAccel && hasGyro) {
+                bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
+                registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
+
+                bool needGameRotationVector =
+                        (virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
+                registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
+            }
+
+            if (hasAccel && hasMag) {
+                bool needGeoMagRotationVector =
+                        (virtualSensorsNeeds & (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) != 0;
+                registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);
+            }
 
             // Check if the device really supports batching by looking at the FIFO event
             // counts for each sensor.
             bool batchingSupported = false;
-            for (size_t i = 0; i < mSensorList.size(); ++i) {
-                if (mSensorList[i].getFifoMaxEventCount() > 0) {
-                    batchingSupported = true;
-                    break;
-                }
-            }
+            mSensors.forEachSensor(
+                    [&batchingSupported] (const Sensor& s) -> bool {
+                        if (s.getFifoMaxEventCount() > 0) {
+                            batchingSupported = true;
+                        }
+                        return !batchingSupported;
+                    });
 
             if (batchingSupported) {
                 // Increase socket buffer size to a max of 100 KB for batching capabilities.
@@ -213,41 +214,46 @@
     }
 }
 
-Sensor SensorService::registerSensor(SensorInterface* s)
-{
-    sensors_event_t event;
-    memset(&event, 0, sizeof(event));
-
-    const Sensor sensor(s->getSensor());
-    // add to the sensor list (returned to clients)
-    mSensorList.add(sensor);
-    // add to our handle->SensorInterface mapping
-    mSensorMap.add(sensor.getHandle(), s);
-    // create an entry in the mLastEventSeen array
-    mLastEventSeen.add(sensor.getHandle(), NULL);
-
-    return sensor;
+const Sensor& SensorService::registerSensor(SensorInterface* s, bool isDebug, bool isVirtual) {
+    int handle = s->getSensor().getHandle();
+    int type = s->getSensor().getType();
+    if (mSensors.add(handle, s, isDebug, isVirtual)){
+        mRecentEvent.emplace(handle, new RecentEventLogger(type));
+        return s->getSensor();
+    } else {
+        return mSensors.getNonSensor();
+    }
 }
 
-Sensor SensorService::registerVirtualSensor(SensorInterface* s)
-{
-    Sensor sensor = registerSensor(s);
-    mVirtualSensorList.add( s );
-    return sensor;
+const Sensor& SensorService::registerDynamicSensorLocked(SensorInterface* s, bool isDebug) {
+    return registerSensor(s, isDebug);
 }
 
-SensorService::~SensorService()
-{
-    for (size_t i=0 ; i<mSensorMap.size() ; i++)
-        delete mSensorMap.valueAt(i);
+bool SensorService::unregisterDynamicSensorLocked(int handle) {
+    bool ret = mSensors.remove(handle);
+
+    const auto i = mRecentEvent.find(handle);
+    if (i != mRecentEvent.end()) {
+        delete i->second;
+        mRecentEvent.erase(i);
+    }
+    return ret;
 }
 
-status_t SensorService::dump(int fd, const Vector<String16>& args)
-{
+const Sensor& SensorService::registerVirtualSensor(SensorInterface* s, bool isDebug) {
+    return registerSensor(s, isDebug, true);
+}
+
+SensorService::~SensorService() {
+    for (auto && entry : mRecentEvent) {
+        delete entry.second;
+    }
+}
+
+status_t SensorService::dump(int fd, const Vector<String16>& args) {
     String8 result;
     if (!PermissionCache::checkCallingPermission(sDump)) {
-        result.appendFormat("Permission Denial: "
-                "can't dump SensorService from pid=%d, uid=%d\n",
+        result.appendFormat("Permission Denial: can't dump SensorService from pid=%d, uid=%d\n",
                 IPCThreadState::self()->getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
     } else {
@@ -305,72 +311,30 @@
                 // Transition to data injection mode supported only from NORMAL mode.
                 return INVALID_OPERATION;
             }
-        } else if (mSensorList.size() == 0) {
+        } else if (!mSensors.hasAnySensor()) {
             result.append("No Sensors on the device\n");
         } else {
             // Default dump the sensor list and debugging information.
+            //
+            result.append("Sensor Device:\n");
+            result.append(SensorDevice::getInstance().dump().c_str());
+
             result.append("Sensor List:\n");
-            for (size_t i=0 ; i<mSensorList.size() ; i++) {
-                const Sensor& s(mSensorList[i]);
-                result.appendFormat(
-                        "%-15s| %-10s| version=%d |%-20s| 0x%08x | \"%s\" | type=%d |",
-                        s.getName().string(),
-                        s.getVendor().string(),
-                        s.getVersion(),
-                        s.getStringType().string(),
-                        s.getHandle(),
-                        s.getRequiredPermission().string(),
-                        s.getType());
+            result.append(mSensors.dump().c_str());
 
-                const int reportingMode = s.getReportingMode();
-                if (reportingMode == AREPORTING_MODE_CONTINUOUS) {
-                    result.append(" continuous | ");
-                } else if (reportingMode == AREPORTING_MODE_ON_CHANGE) {
-                    result.append(" on-change | ");
-                } else if (reportingMode == AREPORTING_MODE_ONE_SHOT) {
-                    result.append(" one-shot | ");
-                } else {
-                    result.append(" special-trigger | ");
-                }
-
-                if (s.getMaxDelay() > 0) {
-                    result.appendFormat("minRate=%.2fHz | ", 1e6f / s.getMaxDelay());
-                } else {
-                    result.appendFormat("maxDelay=%dus |", s.getMaxDelay());
-                }
-
-                if (s.getMinDelay() > 0) {
-                    result.appendFormat("maxRate=%.2fHz | ", 1e6f / s.getMinDelay());
-                } else {
-                    result.appendFormat("minDelay=%dus |", s.getMinDelay());
-                }
-
-                if (s.getFifoMaxEventCount() > 0) {
-                    result.appendFormat("FifoMax=%d events | ",
-                            s.getFifoMaxEventCount());
-                } else {
-                    result.append("no batching | ");
-                }
-
-                if (s.isWakeUpSensor()) {
-                    result.appendFormat("wakeUp | ");
-                } else {
-                    result.appendFormat("non-wakeUp | ");
-                }
-
-                int bufIndex = mLastEventSeen.indexOfKey(s.getHandle());
-                if (bufIndex >= 0) {
-                    const CircularBuffer* buf = mLastEventSeen.valueAt(bufIndex);
-                    if (buf != NULL && s.getRequiredPermission().isEmpty()) {
-                        buf->printBuffer(result);
-                    } else {
-                        result.append("last=<> \n");
-                    }
-                }
-                result.append("\n");
-            }
+            result.append("Fusion States:\n");
             SensorFusion::getInstance().dump(result);
-            SensorDevice::getInstance().dump(result);
+
+            result.append("Recent Sensor events:\n");
+            for (auto&& i : mRecentEvent) {
+                sp<SensorInterface> s = mSensors.getInterface(i.first);
+                if (!i.second->isEmpty() &&
+                    s->getSensor().getRequiredPermission().isEmpty()) {
+                    // if there is events and sensor does not need special permission.
+                    result.appendFormat("%s: ", s->getSensor().getName().string());
+                    result.append(i.second->dump().c_str());
+                }
+            }
 
             result.append("Active sensors:\n");
             for (size_t i=0 ; i<mActiveSensors.size() ; i++) {
@@ -381,7 +345,7 @@
                         mActiveSensors.valueAt(i)->getNumConnections());
             }
 
-            result.appendFormat("Socket Buffer size = %d events\n",
+            result.appendFormat("Socket Buffer size = %zd events\n",
                                 mSocketBufferSize/sizeof(sensors_event_t));
             result.appendFormat("WakeLock Status: %s \n", mWakeLockAcquired ? "acquired" :
                     "not held");
@@ -439,6 +403,7 @@
     return NO_ERROR;
 }
 
+//TODO: move to SensorEventConnection later
 void SensorService::cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
         sensors_event_t const* buffer, const int count) {
     for (int i=0 ; i<count ; i++) {
@@ -447,12 +412,12 @@
             handle = buffer[i].meta_data.sensor;
         }
         if (connection->hasSensor(handle)) {
-            SensorInterface* sensor = mSensorMap.valueFor(handle);
+            sp<SensorInterface> si = getSensorInterfaceFromHandle(handle);
             // If this buffer has an event from a one_shot sensor and this connection is registered
             // for this particular one_shot sensor, try cleaning up the connection.
-            if (sensor != NULL &&
-                sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
-                sensor->autoDisable(connection.get(), handle);
+            if (si != nullptr &&
+                si->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
+                si->autoDisable(connection.get(), handle);
                 cleanupWithoutDisableLocked(connection, handle);
             }
 
@@ -460,18 +425,17 @@
    }
 }
 
-bool SensorService::threadLoop()
-{
+bool SensorService::threadLoop() {
     ALOGD("nuSensorService thread starting...");
 
-    // each virtual sensor could generate an event per "real" event, that's why we need
-    // to size numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.
-    // in practice, this is too aggressive, but guaranteed to be enough.
+    // each virtual sensor could generate an event per "real" event, that's why we need to size
+    // numEventMax much smaller than MAX_RECEIVE_BUFFER_EVENT_COUNT.  in practice, this is too
+    // aggressive, but guaranteed to be enough.
+    const size_t vcount = mSensors.getVirtualSensors().size();
     const size_t minBufferSize = SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT;
-    const size_t numEventMax = minBufferSize / (1 + mVirtualSensorList.size());
+    const size_t numEventMax = minBufferSize / (1 + vcount);
 
     SensorDevice& device(SensorDevice::getInstance());
-    const size_t vcount = mVirtualSensorList.size();
 
     const int halVersion = device.getHalDeviceVersion();
     do {
@@ -486,14 +450,15 @@
              mSensorEventBuffer[i].flags = 0;
         }
 
-        // Make a copy of the connection vector as some connections may be removed during the
-        // course of this loop (especially when one-shot sensor events are present in the
-        // sensor_event buffer). Promote all connections to StrongPointers before the lock is
-        // acquired. If the destructor of the sp gets called when the lock is acquired, it may
-        // result in a deadlock as ~SensorEventConnection() needs to acquire mLock again for
-        // cleanup. So copy all the strongPointers to a vector before the lock is acquired.
+        // Make a copy of the connection vector as some connections may be removed during the course
+        // of this loop (especially when one-shot sensor events are present in the sensor_event
+        // buffer). Promote all connections to StrongPointers before the lock is acquired. If the
+        // destructor of the sp gets called when the lock is acquired, it may result in a deadlock
+        // as ~SensorEventConnection() needs to acquire mLock again for cleanup. So copy all the
+        // strongPointers to a vector before the lock is acquired.
         SortedVector< sp<SensorEventConnection> > activeConnections;
         populateActiveConnections(&activeConnections);
+
         Mutex::Autolock _l(mLock);
         // Poll has returned. Hold a wakelock if one of the events is from a wake up sensor. The
         // rest of this loop is under a critical section protected by mLock. Acquiring a wakeLock,
@@ -516,8 +481,7 @@
         // handle virtual sensors
         if (count && vcount) {
             sensors_event_t const * const event = mSensorEventBuffer;
-            const size_t activeVirtualSensorCount = mActiveVirtualSensors.size();
-            if (activeVirtualSensorCount) {
+            if (!mActiveVirtualSensors.empty()) {
                 size_t k = 0;
                 SensorFusion& fusion(SensorFusion::getInstance());
                 if (fusion.isEnabled()) {
@@ -526,7 +490,7 @@
                     }
                 }
                 for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
-                    for (size_t j=0 ; j<activeVirtualSensorCount ; j++) {
+                    for (int handle : mActiveVirtualSensors) {
                         if (count + k >= minBufferSize) {
                             ALOGE("buffer too small to hold all events: "
                                     "count=%zd, k=%zu, size=%zu",
@@ -534,7 +498,12 @@
                             break;
                         }
                         sensors_event_t out;
-                        SensorInterface* si = mActiveVirtualSensors.valueAt(j);
+                        sp<SensorInterface> si = mSensors.getInterface(handle);
+                        if (si == nullptr) {
+                            ALOGE("handle %d is not an valid virtual sensor", handle);
+                            continue;
+                        }
+
                         if (si->process(&out, event[i])) {
                             mSensorEventBuffer[count + k] = out;
                             k++;
@@ -562,11 +531,11 @@
             }
         }
 
-        // Map flush_complete_events in the buffer to SensorEventConnections which called
-        // flush on the hardware sensor. mapFlushEventsToConnections[i] will be the
-        // SensorEventConnection mapped to the corresponding flush_complete_event in
-        // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
         for (int i = 0; i < count; ++i) {
+            // Map flush_complete_events in the buffer to SensorEventConnections which called flush
+            // on the hardware sensor. mapFlushEventsToConnections[i] will be the
+            // SensorEventConnection mapped to the corresponding flush_complete_event in
+            // mSensorEventBuffer[i] if such a mapping exists (NULL otherwise).
             mMapFlushEventsToConnections[i] = NULL;
             if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
                 const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
@@ -576,8 +545,54 @@
                     rec->removeFirstPendingFlushConnection();
                 }
             }
+
+            // handle dynamic sensor meta events, process registration and unregistration of dynamic
+            // sensor based on content of event.
+            if (mSensorEventBuffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
+                if (mSensorEventBuffer[i].dynamic_sensor_meta.connected) {
+                    int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
+                    const sensor_t& dynamicSensor =
+                            *(mSensorEventBuffer[i].dynamic_sensor_meta.sensor);
+                    ALOGI("Dynamic sensor handle 0x%x connected, type %d, name %s",
+                          handle, dynamicSensor.type, dynamicSensor.name);
+
+                    if (mSensors.isNewHandle(handle)) {
+                        const auto& uuid = mSensorEventBuffer[i].dynamic_sensor_meta.uuid;
+                        sensor_t s = dynamicSensor;
+                        // make sure the dynamic sensor flag is set
+                        s.flags |= DYNAMIC_SENSOR_MASK;
+                        // force the handle to be consistent
+                        s.handle = handle;
+
+                        SensorInterface *si = new HardwareSensor(s, uuid);
+
+                        // This will release hold on dynamic sensor meta, so it should be called
+                        // after Sensor object is created.
+                        device.handleDynamicSensorConnection(handle, true /*connected*/);
+                        registerDynamicSensorLocked(si);
+                    } else {
+                        ALOGE("Handle %d has been used, cannot use again before reboot.", handle);
+                    }
+                } else {
+                    int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
+                    ALOGI("Dynamic sensor handle 0x%x disconnected", handle);
+
+                    device.handleDynamicSensorConnection(handle, false /*connected*/);
+                    if (!unregisterDynamicSensorLocked(handle)) {
+                        ALOGE("Dynamic sensor release error.");
+                    }
+
+                    size_t numConnections = activeConnections.size();
+                    for (size_t i=0 ; i < numConnections; ++i) {
+                        if (activeConnections[i] != NULL) {
+                            activeConnections[i]->removeSensor(handle);
+                        }
+                    }
+                }
+            }
         }
 
+
         // Send our events to clients. Check the state of wake lock for each client and release the
         // lock if none of the clients need it.
         bool needsWakeLock = false;
@@ -662,18 +677,20 @@
 void SensorService::recordLastValueLocked(
         const sensors_event_t* buffer, size_t count) {
     for (size_t i = 0; i < count; i++) {
-        if (buffer[i].type != SENSOR_TYPE_META_DATA) {
-            CircularBuffer* &circular_buf = mLastEventSeen.editValueFor(buffer[i].sensor);
-            if (circular_buf == NULL) {
-                circular_buf = new CircularBuffer(buffer[i].type);
-            }
-            circular_buf->addEvent(buffer[i]);
+        if (buffer[i].type == SENSOR_TYPE_META_DATA ||
+            buffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META ||
+            buffer[i].type == SENSOR_TYPE_ADDITIONAL_INFO) {
+            continue;
+        }
+
+        auto logger = mRecentEvent.find(buffer[i].sensor);
+        if (logger != mRecentEvent.end()) {
+            logger->second->addEvent(buffer[i]);
         }
     }
 }
 
-void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count)
-{
+void SensorService::sortEventBuffer(sensors_event_t* buffer, size_t count) {
     struct compar {
         static int cmp(void const* lhs, void const* rhs) {
             sensors_event_t const* l = static_cast<sensors_event_t const*>(lhs);
@@ -685,20 +702,12 @@
 }
 
 String8 SensorService::getSensorName(int handle) const {
-    size_t count = mUserSensorList.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const Sensor& sensor(mUserSensorList[i]);
-        if (sensor.getHandle() == handle) {
-            return sensor.getName();
-        }
-    }
-    String8 result("unknown");
-    return result;
+    return mSensors.getName(handle);
 }
 
 bool SensorService::isVirtualSensor(int handle) const {
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    return sensor->isVirtual();
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    return sensor != nullptr && sensor->isVirtual();
 }
 
 bool SensorService::isWakeUpSensorEvent(const sensors_event_t& event) const {
@@ -706,20 +715,15 @@
     if (event.type == SENSOR_TYPE_META_DATA) {
         handle = event.meta_data.sensor;
     }
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    return sensor != NULL && sensor->getSensor().isWakeUpSensor();
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    return sensor != nullptr && sensor->getSensor().isWakeUpSensor();
 }
 
-SensorService::SensorRecord * SensorService::getSensorRecord(int handle) {
-     return mActiveSensors.valueFor(handle);
-}
-
-Vector<Sensor> SensorService::getSensorList(const String16& opPackageName)
-{
+Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.sensors", value, "0");
     const Vector<Sensor>& initialSensorList = (atoi(value)) ?
-            mUserSensorListDebug : mUserSensorList;
+            mSensors.getUserDebugSensors() : mSensors.getUserSensors();
     Vector<Sensor> accessibleSensorList;
     for (size_t i = 0; i < initialSensorList.size(); i++) {
         Sensor sensor = initialSensorList[i];
@@ -735,6 +739,25 @@
     return accessibleSensorList;
 }
 
+Vector<Sensor> SensorService::getDynamicSensorList(const String16& opPackageName) {
+    Vector<Sensor> accessibleSensorList;
+    mSensors.forEachSensor(
+            [&opPackageName, &accessibleSensorList] (const Sensor& sensor) -> bool {
+                if (sensor.isDynamicSensor()) {
+                    if (canAccessSensor(sensor, "getDynamicSensorList", opPackageName)) {
+                        accessibleSensorList.add(sensor);
+                    } else {
+                        ALOGI("Skipped sensor %s because it requires permission %s and app op %" PRId32,
+                              sensor.getName().string(),
+                              sensor.getRequiredPermission().string(),
+                              sensor.getRequiredAppOp());
+                    }
+                }
+                return true;
+            });
+    return accessibleSensorList;
+}
+
 sp<ISensorEventConnection> SensorService::createSensorEventConnection(const String8& packageName,
         int requestedMode, const String16& opPackageName) {
     // Only 2 modes supported for a SensorEventConnection ... NORMAL and DATA_INJECTION.
@@ -782,8 +805,7 @@
     return err;
 }
 
-void SensorService::cleanupConnection(SensorEventConnection* c)
-{
+void SensorService::cleanupConnection(SensorEventConnection* c) {
     Mutex::Autolock _l(mLock);
     const wp<SensorEventConnection> connection(c);
     size_t size = mActiveSensors.size();
@@ -792,10 +814,11 @@
         int handle = mActiveSensors.keyAt(i);
         if (c->hasSensor(handle)) {
             ALOGD_IF(DEBUG_CONNECTIONS, "%zu: disabling handle=0x%08x", i, handle);
-            SensorInterface* sensor = mSensorMap.valueFor( handle );
-            ALOGE_IF(!sensor, "mSensorMap[handle=0x%08x] is null!", handle);
-            if (sensor) {
+            sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+            if (sensor != nullptr) {
                 sensor->activate(c, false);
+            } else {
+                ALOGE("sensor interface of handle=0x%08x is null!", handle);
             }
             c->removeSensor(handle);
         }
@@ -808,7 +831,7 @@
         if (rec && rec->removeConnection(connection)) {
             ALOGD_IF(DEBUG_CONNECTIONS, "... and it was the last connection");
             mActiveSensors.removeItemsAt(i, 1);
-            mActiveVirtualSensors.removeItem(handle);
+            mActiveVirtualSensors.erase(handle);
             delete rec;
             size--;
         } else {
@@ -823,23 +846,20 @@
     }
 }
 
-Sensor SensorService::getSensorFromHandle(int handle) const {
-    return mSensorMap.valueFor(handle)->getSensor();
+sp<SensorInterface> SensorService::getSensorInterfaceFromHandle(int handle) const {
+    return mSensors.getInterface(handle);
 }
 
+
 status_t SensorService::enable(const sp<SensorEventConnection>& connection,
         int handle, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs, int reservedFlags,
-        const String16& opPackageName)
-{
+        const String16& opPackageName) {
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    if (sensor == NULL) {
-        return BAD_VALUE;
-    }
-
-    if (!canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    if (sensor == nullptr ||
+        !canAccessSensor(sensor->getSensor(), "Tried enabling", opPackageName)) {
         return BAD_VALUE;
     }
 
@@ -854,7 +874,7 @@
         rec = new SensorRecord(connection);
         mActiveSensors.add(handle, rec);
         if (sensor->isVirtual()) {
-            mActiveVirtualSensors.add(handle, sensor);
+            mActiveVirtualSensors.emplace(handle);
         }
     } else {
         if (rec->addConnection(connection)) {
@@ -864,14 +884,14 @@
             if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ON_CHANGE) {
                 // NOTE: The wake_up flag of this event may get set to
                 // WAKE_UP_SENSOR_EVENT_NEEDS_ACK if this is a wake_up event.
-                CircularBuffer *circular_buf = mLastEventSeen.valueFor(handle);
-                if (circular_buf) {
+
+                auto logger = mRecentEvent.find(handle);
+                if (logger != mRecentEvent.end()) {
                     sensors_event_t event;
-                    memset(&event, 0, sizeof(event));
                     // It is unlikely that this buffer is empty as the sensor is already active.
                     // One possible corner case may be two applications activating an on-change
                     // sensor at the same time.
-                    if(circular_buf->populateLastEvent(&event)) {
+                    if(logger->second->populateLastEvent(&event)) {
                         event.sensor = handle;
                         if (event.version == sizeof(sensors_event_t)) {
                             if (isWakeUpSensorEvent(event) && !mWakeLockAcquired) {
@@ -919,8 +939,7 @@
     // one should be trigger by a change in value). Also if this sensor isn't
     // already active, don't call flush().
     if (err == NO_ERROR &&
-            sensor->getSensor().getReportingMode() != AREPORTING_MODE_ONE_SHOT &&
-            sensor->getSensor().getReportingMode() != AREPORTING_MODE_ON_CHANGE &&
+            sensor->getSensor().getReportingMode() == AREPORTING_MODE_CONTINUOUS &&
             rec->getNumConnections() > 1) {
         connection->setFirstFlushPending(handle, true);
         status_t err_flush = sensor->flush(connection.get(), handle);
@@ -961,17 +980,15 @@
     return err;
 }
 
-status_t SensorService::disable(const sp<SensorEventConnection>& connection,
-        int handle)
-{
+status_t SensorService::disable(const sp<SensorEventConnection>& connection, int handle) {
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
     Mutex::Autolock _l(mLock);
     status_t err = cleanupWithoutDisableLocked(connection, handle);
     if (err == NO_ERROR) {
-        SensorInterface* sensor = mSensorMap.valueFor(handle);
-        err = sensor ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
+        sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+        err = sensor != nullptr ? sensor->activate(connection.get(), false) : status_t(BAD_VALUE);
 
     }
     if (err == NO_ERROR) {
@@ -1011,7 +1028,7 @@
         // see if this sensor becomes inactive
         if (rec->removeConnection(connection)) {
             mActiveSensors.removeItem(handle);
-            mActiveVirtualSensors.removeItem(handle);
+            mActiveVirtualSensors.erase(handle);
             delete rec;
         }
         return NO_ERROR;
@@ -1020,16 +1037,13 @@
 }
 
 status_t SensorService::setEventRate(const sp<SensorEventConnection>& connection,
-        int handle, nsecs_t ns, const String16& opPackageName)
-{
+        int handle, nsecs_t ns, const String16& opPackageName) {
     if (mInitCheck != NO_ERROR)
         return mInitCheck;
 
-    SensorInterface* sensor = mSensorMap.valueFor(handle);
-    if (!sensor)
-        return BAD_VALUE;
-
-    if (!canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
+    sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+    if (sensor == nullptr ||
+        !canAccessSensor(sensor->getSensor(), "Tried configuring", opPackageName)) {
         return BAD_VALUE;
     }
 
@@ -1054,7 +1068,10 @@
     // Loop through all sensors for this connection and call flush on each of them.
     for (size_t i = 0; i < connection->mSensorInfo.size(); ++i) {
         const int handle = connection->mSensorInfo.keyAt(i);
-        SensorInterface* sensor = mSensorMap.valueFor(handle);
+        sp<SensorInterface> sensor = getSensorInterfaceFromHandle(handle);
+        if (sensor == nullptr) {
+            continue;
+        }
         if (sensor->getSensor().getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
             ALOGE("flush called on a one-shot sensor");
             err = INVALID_OPERATION;
@@ -1109,7 +1126,7 @@
         AppOpsManager appOps;
         if (appOps.noteOp(opCode, IPCThreadState::self()->getCallingUid(), opPackageName)
                         != AppOpsManager::MODE_ALLOWED) {
-            ALOGE("%s a sensor (%s) without enabled required app op: %D",
+            ALOGE("%s a sensor (%s) without enabled required app op: %d",
                     operation, sensor.getName().string(), opCode);
             return false;
         }
@@ -1165,805 +1182,5 @@
     return (packageName.contains(mWhiteListedPackage.string()));
 }
 
-int SensorService::getNumEventsForSensorType(int sensor_event_type) {
-    if (sensor_event_type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
-        return 16;
-    }
-    switch (sensor_event_type) {
-        case SENSOR_TYPE_ROTATION_VECTOR:
-        case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
-            return 5;
-
-        case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
-        case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
-            return 6;
-
-        case SENSOR_TYPE_GAME_ROTATION_VECTOR:
-            return 4;
-
-        case SENSOR_TYPE_SIGNIFICANT_MOTION:
-        case SENSOR_TYPE_STEP_DETECTOR:
-        case SENSOR_TYPE_STEP_COUNTER:
-            return 1;
-
-         default:
-            return 3;
-    }
-}
-
-// ---------------------------------------------------------------------------
-SensorService::SensorRecord::SensorRecord(
-        const sp<SensorEventConnection>& connection)
-{
-    mConnections.add(connection);
-}
-
-bool SensorService::SensorRecord::addConnection(
-        const sp<SensorEventConnection>& connection)
-{
-    if (mConnections.indexOf(connection) < 0) {
-        mConnections.add(connection);
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorRecord::removeConnection(
-        const wp<SensorEventConnection>& connection)
-{
-    ssize_t index = mConnections.indexOf(connection);
-    if (index >= 0) {
-        mConnections.removeItemsAt(index, 1);
-    }
-    // Remove this connections from the queue of flush() calls made on this sensor.
-    for (Vector< wp<SensorEventConnection> >::iterator it =
-            mPendingFlushConnections.begin(); it != mPendingFlushConnections.end();) {
-
-        if (it->unsafe_get() == connection.unsafe_get()) {
-            it = mPendingFlushConnections.erase(it);
-        } else {
-            ++it;
-        }
-    }
-    return mConnections.size() ? false : true;
-}
-
-void SensorService::SensorRecord::addPendingFlushConnection(
-        const sp<SensorEventConnection>& connection) {
-    mPendingFlushConnections.add(connection);
-}
-
-void SensorService::SensorRecord::removeFirstPendingFlushConnection() {
-    if (mPendingFlushConnections.size() > 0) {
-        mPendingFlushConnections.removeAt(0);
-    }
-}
-
-SensorService::SensorEventConnection *
-SensorService::SensorRecord::getFirstPendingFlushConnection() {
-   if (mPendingFlushConnections.size() > 0) {
-        return mPendingFlushConnections[0].unsafe_get();
-    }
-    return NULL;
-}
-
-void SensorService::SensorRecord::clearAllPendingFlushConnections() {
-    mPendingFlushConnections.clear();
-}
-
-
-// ---------------------------------------------------------------------------
-SensorService::TrimmedSensorEvent::TrimmedSensorEvent(int sensorType) {
-    mTimestamp = -1;
-    const int numData = SensorService::getNumEventsForSensorType(sensorType);
-    if (sensorType == SENSOR_TYPE_STEP_COUNTER) {
-        mStepCounter = 0;
-    } else {
-        mData = new float[numData];
-        for (int i = 0; i < numData; ++i) {
-            mData[i] = -1.0;
-        }
-    }
-    mHour = mMin = mSec = INT32_MIN;
-}
-
-bool SensorService::TrimmedSensorEvent::isSentinel(const TrimmedSensorEvent& event) {
-    return (event.mHour == INT32_MIN && event.mMin == INT32_MIN && event.mSec == INT32_MIN);
-}
-// --------------------------------------------------------------------------
-SensorService::CircularBuffer::CircularBuffer(int sensor_event_type) {
-    mNextInd = 0;
-    mBufSize = CIRCULAR_BUF_SIZE;
-    if (sensor_event_type == SENSOR_TYPE_STEP_COUNTER ||
-            sensor_event_type == SENSOR_TYPE_SIGNIFICANT_MOTION ||
-            sensor_event_type == SENSOR_TYPE_ACCELEROMETER) {
-        mBufSize = CIRCULAR_BUF_SIZE * 5;
-    }
-    mTrimmedSensorEventArr = new TrimmedSensorEvent *[mBufSize];
-    mSensorType = sensor_event_type;
-    for (int i = 0; i < mBufSize; ++i) {
-        mTrimmedSensorEventArr[i] = new TrimmedSensorEvent(mSensorType);
-    }
-}
-
-void SensorService::CircularBuffer::addEvent(const sensors_event_t& sensor_event) {
-    TrimmedSensorEvent *curr_event = mTrimmedSensorEventArr[mNextInd];
-    curr_event->mTimestamp = sensor_event.timestamp;
-    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-        curr_event->mStepCounter = sensor_event.u64.step_counter;
-    } else {
-        memcpy(curr_event->mData, sensor_event.data,
-                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
-    }
-    time_t rawtime = time(NULL);
-    struct tm * timeinfo = localtime(&rawtime);
-    curr_event->mHour = timeinfo->tm_hour;
-    curr_event->mMin = timeinfo->tm_min;
-    curr_event->mSec = timeinfo->tm_sec;
-    mNextInd = (mNextInd + 1) % mBufSize;
-}
-
-void SensorService::CircularBuffer::printBuffer(String8& result) const {
-    const int numData = SensorService::getNumEventsForSensorType(mSensorType);
-    int i = mNextInd, eventNum = 1;
-    result.appendFormat("last %d events = < ", mBufSize);
-    do {
-        if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[i])) {
-            // Sentinel, ignore.
-            i = (i + 1) % mBufSize;
-            continue;
-        }
-        result.appendFormat("%d) ", eventNum++);
-        if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-            result.appendFormat("%llu,", mTrimmedSensorEventArr[i]->mStepCounter);
-        } else {
-            for (int j = 0; j < numData; ++j) {
-                result.appendFormat("%5.1f,", mTrimmedSensorEventArr[i]->mData[j]);
-            }
-        }
-        result.appendFormat("%lld %02d:%02d:%02d ", mTrimmedSensorEventArr[i]->mTimestamp,
-                mTrimmedSensorEventArr[i]->mHour, mTrimmedSensorEventArr[i]->mMin,
-                mTrimmedSensorEventArr[i]->mSec);
-        i = (i + 1) % mBufSize;
-    } while (i != mNextInd);
-    result.appendFormat(">\n");
-}
-
-bool SensorService::CircularBuffer::populateLastEvent(sensors_event_t *event) {
-    int lastEventInd = (mNextInd - 1 + mBufSize) % mBufSize;
-    // Check if the buffer is empty.
-    if (TrimmedSensorEvent::isSentinel(*mTrimmedSensorEventArr[lastEventInd])) {
-        return false;
-    }
-    event->version = sizeof(sensors_event_t);
-    event->type = mSensorType;
-    event->timestamp = mTrimmedSensorEventArr[lastEventInd]->mTimestamp;
-    if (mSensorType == SENSOR_TYPE_STEP_COUNTER) {
-          event->u64.step_counter = mTrimmedSensorEventArr[lastEventInd]->mStepCounter;
-    } else {
-        memcpy(event->data, mTrimmedSensorEventArr[lastEventInd]->mData,
-                 sizeof(float) * SensorService::getNumEventsForSensorType(mSensorType));
-    }
-    return true;
-}
-
-SensorService::CircularBuffer::~CircularBuffer() {
-    for (int i = 0; i < mBufSize; ++i) {
-        delete mTrimmedSensorEventArr[i];
-    }
-    delete [] mTrimmedSensorEventArr;
-}
-
-// ---------------------------------------------------------------------------
-
-SensorService::SensorEventConnection::SensorEventConnection(
-        const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
-        const String16& opPackageName)
-    : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
-      mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(NULL),
-      mCacheSize(0), mMaxCacheSize(0), mPackageName(packageName), mOpPackageName(opPackageName) {
-    mChannel = new BitTube(mService->mSocketBufferSize);
-#if DEBUG_CONNECTIONS
-    mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
-    mTotalAcksNeeded = mTotalAcksReceived = 0;
-#endif
-}
-
-SensorService::SensorEventConnection::~SensorEventConnection() {
-    ALOGD_IF(DEBUG_CONNECTIONS, "~SensorEventConnection(%p)", this);
-    mService->cleanupConnection(this);
-    if (mEventCache != NULL) {
-        delete mEventCache;
-    }
-}
-
-void SensorService::SensorEventConnection::onFirstRef() {
-    LooperCallback::onFirstRef();
-}
-
-bool SensorService::SensorEventConnection::needsWakeLock() {
-    Mutex::Autolock _l(mConnectionLock);
-    return !mDead && mWakeLockRefCount > 0;
-}
-
-void SensorService::SensorEventConnection::resetWakeLockRefCount() {
-    Mutex::Autolock _l(mConnectionLock);
-    mWakeLockRefCount = 0;
-}
-
-void SensorService::SensorEventConnection::dump(String8& result) {
-    Mutex::Autolock _l(mConnectionLock);
-    result.appendFormat("\tOperating Mode: %s\n",mDataInjectionMode ? "DATA_INJECTION" : "NORMAL");
-    result.appendFormat("\t %s | WakeLockRefCount %d | uid %d | cache size %d | "
-            "max cache size %d\n", mPackageName.string(), mWakeLockRefCount, mUid, mCacheSize,
-            mMaxCacheSize);
-    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        const FlushInfo& flushInfo = mSensorInfo.valueAt(i);
-        result.appendFormat("\t %s 0x%08x | status: %s | pending flush events %d \n",
-                            mService->getSensorName(mSensorInfo.keyAt(i)).string(),
-                            mSensorInfo.keyAt(i),
-                            flushInfo.mFirstFlushPending ? "First flush pending" :
-                                                           "active",
-                            flushInfo.mPendingFlushEventsToSend);
-    }
-#if DEBUG_CONNECTIONS
-    result.appendFormat("\t events recvd: %d | sent %d | cache %d | dropped %d |"
-            " total_acks_needed %d | total_acks_recvd %d\n",
-            mEventsReceived,
-            mEventsSent,
-            mEventsSentFromCache,
-            mEventsReceived - (mEventsSentFromCache + mEventsSent + mCacheSize),
-            mTotalAcksNeeded,
-            mTotalAcksReceived);
-#endif
-}
-
-bool SensorService::SensorEventConnection::addSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (!canAccessSensor(mService->getSensorFromHandle(handle),
-            "Tried adding", mOpPackageName)) {
-        return false;
-    }
-    if (mSensorInfo.indexOfKey(handle) < 0) {
-        mSensorInfo.add(handle, FlushInfo());
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorEventConnection::removeSensor(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    if (mSensorInfo.removeItem(handle) >= 0) {
-        return true;
-    }
-    return false;
-}
-
-bool SensorService::SensorEventConnection::hasSensor(int32_t handle) const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.indexOfKey(handle) >= 0;
-}
-
-bool SensorService::SensorEventConnection::hasAnySensor() const {
-    Mutex::Autolock _l(mConnectionLock);
-    return mSensorInfo.size() ? true : false;
-}
-
-bool SensorService::SensorEventConnection::hasOneShotSensors() const {
-    Mutex::Autolock _l(mConnectionLock);
-    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        const int handle = mSensorInfo.keyAt(i);
-        if (mService->getSensorFromHandle(handle).getReportingMode() == AREPORTING_MODE_ONE_SHOT) {
-            return true;
-        }
-    }
-    return false;
-}
-
-String8 SensorService::SensorEventConnection::getPackageName() const {
-    return mPackageName;
-}
-
-void SensorService::SensorEventConnection::setFirstFlushPending(int32_t handle,
-                                bool value) {
-    Mutex::Autolock _l(mConnectionLock);
-    ssize_t index = mSensorInfo.indexOfKey(handle);
-    if (index >= 0) {
-        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
-        flushInfo.mFirstFlushPending = value;
-    }
-}
-
-void SensorService::SensorEventConnection::updateLooperRegistration(const sp<Looper>& looper) {
-    Mutex::Autolock _l(mConnectionLock);
-    updateLooperRegistrationLocked(looper);
-}
-
-void SensorService::SensorEventConnection::updateLooperRegistrationLocked(
-        const sp<Looper>& looper) {
-    bool isConnectionActive = (mSensorInfo.size() > 0 && !mDataInjectionMode) ||
-                              mDataInjectionMode;
-    // If all sensors are unregistered OR Looper has encountered an error, we
-    // can remove the Fd from the Looper if it has been previously added.
-    if (!isConnectionActive || mDead) {
-        if (mHasLooperCallbacks) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "%p removeFd fd=%d", this, mChannel->getSendFd());
-            looper->removeFd(mChannel->getSendFd());
-            mHasLooperCallbacks = false;
-        }
-        return;
-    }
-
-    int looper_flags = 0;
-    if (mCacheSize > 0) looper_flags |= ALOOPER_EVENT_OUTPUT;
-    if (mDataInjectionMode) looper_flags |= ALOOPER_EVENT_INPUT;
-    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        const int handle = mSensorInfo.keyAt(i);
-        if (mService->getSensorFromHandle(handle).isWakeUpSensor()) {
-            looper_flags |= ALOOPER_EVENT_INPUT;
-            break;
-        }
-    }
-    // If flags is still set to zero, we don't need to add this fd to the Looper, if
-    // the fd has already been added, remove it. This is likely to happen when ALL the
-    // events stored in the cache have been sent to the corresponding app.
-    if (looper_flags == 0) {
-        if (mHasLooperCallbacks) {
-            ALOGD_IF(DEBUG_CONNECTIONS, "removeFd fd=%d", mChannel->getSendFd());
-            looper->removeFd(mChannel->getSendFd());
-            mHasLooperCallbacks = false;
-        }
-        return;
-    }
-    // Add the file descriptor to the Looper for receiving acknowledegments if the app has
-    // registered for wake-up sensors OR for sending events in the cache.
-    int ret = looper->addFd(mChannel->getSendFd(), 0, looper_flags, this, NULL);
-    if (ret == 1) {
-        ALOGD_IF(DEBUG_CONNECTIONS, "%p addFd fd=%d", this, mChannel->getSendFd());
-        mHasLooperCallbacks = true;
-    } else {
-        ALOGE("Looper::addFd failed ret=%d fd=%d", ret, mChannel->getSendFd());
-    }
-}
-
-void SensorService::SensorEventConnection::incrementPendingFlushCount(int32_t handle) {
-    Mutex::Autolock _l(mConnectionLock);
-    ssize_t index = mSensorInfo.indexOfKey(handle);
-    if (index >= 0) {
-        FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
-        flushInfo.mPendingFlushEventsToSend++;
-    }
-}
-
-status_t SensorService::SensorEventConnection::sendEvents(
-        sensors_event_t const* buffer, size_t numEvents,
-        sensors_event_t* scratch,
-        SensorEventConnection const * const * mapFlushEventsToConnections) {
-    // filter out events not for this connection
-    int count = 0;
-    Mutex::Autolock _l(mConnectionLock);
-    if (scratch) {
-        size_t i=0;
-        while (i<numEvents) {
-            int32_t sensor_handle = buffer[i].sensor;
-            if (buffer[i].type == SENSOR_TYPE_META_DATA) {
-                ALOGD_IF(DEBUG_CONNECTIONS, "flush complete event sensor==%d ",
-                        buffer[i].meta_data.sensor);
-                // Setting sensor_handle to the correct sensor to ensure the sensor events per
-                // connection are filtered correctly.  buffer[i].sensor is zero for meta_data
-                // events.
-                sensor_handle = buffer[i].meta_data.sensor;
-            }
-            ssize_t index = mSensorInfo.indexOfKey(sensor_handle);
-            // Check if this connection has registered for this sensor. If not continue to the
-            // next sensor_event.
-            if (index < 0) {
-                ++i;
-                continue;
-            }
-
-            FlushInfo& flushInfo = mSensorInfo.editValueAt(index);
-            // Check if there is a pending flush_complete event for this sensor on this connection.
-            if (buffer[i].type == SENSOR_TYPE_META_DATA && flushInfo.mFirstFlushPending == true &&
-                    this == mapFlushEventsToConnections[i]) {
-                flushInfo.mFirstFlushPending = false;
-                ALOGD_IF(DEBUG_CONNECTIONS, "First flush event for sensor==%d ",
-                        buffer[i].meta_data.sensor);
-                ++i;
-                continue;
-            }
-
-            // If there is a pending flush complete event for this sensor on this connection,
-            // ignore the event and proceed to the next.
-            if (flushInfo.mFirstFlushPending) {
-                ++i;
-                continue;
-            }
-
-            do {
-                // Keep copying events into the scratch buffer as long as they are regular
-                // sensor_events are from the same sensor_handle OR they are flush_complete_events
-                // from the same sensor_handle AND the current connection is mapped to the
-                // corresponding flush_complete_event.
-                if (buffer[i].type == SENSOR_TYPE_META_DATA) {
-                    if (this == mapFlushEventsToConnections[i]) {
-                        scratch[count++] = buffer[i];
-                    }
-                    ++i;
-                } else {
-                    // Regular sensor event, just copy it to the scratch buffer.
-                    scratch[count++] = buffer[i++];
-                }
-            } while ((i<numEvents) && ((buffer[i].sensor == sensor_handle &&
-                                        buffer[i].type != SENSOR_TYPE_META_DATA) ||
-                                       (buffer[i].type == SENSOR_TYPE_META_DATA  &&
-                                        buffer[i].meta_data.sensor == sensor_handle)));
-        }
-    } else {
-        scratch = const_cast<sensors_event_t *>(buffer);
-        count = numEvents;
-    }
-
-    sendPendingFlushEventsLocked();
-    // Early return if there are no events for this connection.
-    if (count == 0) {
-        return status_t(NO_ERROR);
-    }
-
-#if DEBUG_CONNECTIONS
-     mEventsReceived += count;
-#endif
-    if (mCacheSize != 0) {
-        // There are some events in the cache which need to be sent first. Copy this buffer to
-        // the end of cache.
-        if (mCacheSize + count <= mMaxCacheSize) {
-            memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
-            mCacheSize += count;
-        } else {
-            // Check if any new sensors have registered on this connection which may have increased
-            // the max cache size that is desired.
-            if (mCacheSize + count < computeMaxCacheSizeLocked()) {
-                reAllocateCacheLocked(scratch, count);
-                return status_t(NO_ERROR);
-            }
-            // Some events need to be dropped.
-            int remaningCacheSize = mMaxCacheSize - mCacheSize;
-            if (remaningCacheSize != 0) {
-                memcpy(&mEventCache[mCacheSize], scratch,
-                                                remaningCacheSize * sizeof(sensors_event_t));
-            }
-            int numEventsDropped = count - remaningCacheSize;
-            countFlushCompleteEventsLocked(mEventCache, numEventsDropped);
-            // Drop the first "numEventsDropped" in the cache.
-            memmove(mEventCache, &mEventCache[numEventsDropped],
-                    (mCacheSize - numEventsDropped) * sizeof(sensors_event_t));
-
-            // Copy the remainingEvents in scratch buffer to the end of cache.
-            memcpy(&mEventCache[mCacheSize - numEventsDropped], scratch + remaningCacheSize,
-                                            numEventsDropped * sizeof(sensors_event_t));
-        }
-        return status_t(NO_ERROR);
-    }
-
-    int index_wake_up_event = findWakeUpSensorEventLocked(scratch, count);
-    if (index_wake_up_event >= 0) {
-        scratch[index_wake_up_event].flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-        ++mWakeLockRefCount;
-#if DEBUG_CONNECTIONS
-        ++mTotalAcksNeeded;
-#endif
-    }
-
-    // NOTE: ASensorEvent and sensors_event_t are the same type.
-    ssize_t size = SensorEventQueue::write(mChannel,
-                                    reinterpret_cast<ASensorEvent const*>(scratch), count);
-    if (size < 0) {
-        // Write error, copy events to local cache.
-        if (index_wake_up_event >= 0) {
-            // If there was a wake_up sensor_event, reset the flag.
-            scratch[index_wake_up_event].flags &= ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-            if (mWakeLockRefCount > 0) {
-                --mWakeLockRefCount;
-            }
-#if DEBUG_CONNECTIONS
-            --mTotalAcksNeeded;
-#endif
-        }
-        if (mEventCache == NULL) {
-            mMaxCacheSize = computeMaxCacheSizeLocked();
-            mEventCache = new sensors_event_t[mMaxCacheSize];
-            mCacheSize = 0;
-        }
-        memcpy(&mEventCache[mCacheSize], scratch, count * sizeof(sensors_event_t));
-        mCacheSize += count;
-
-        // Add this file descriptor to the looper to get a callback when this fd is available for
-        // writing.
-        updateLooperRegistrationLocked(mService->getLooper());
-        return size;
-    }
-
-#if DEBUG_CONNECTIONS
-    if (size > 0) {
-        mEventsSent += count;
-    }
-#endif
-
-    return size < 0 ? status_t(size) : status_t(NO_ERROR);
-}
-
-void SensorService::SensorEventConnection::reAllocateCacheLocked(sensors_event_t const* scratch,
-                                                                 int count) {
-    sensors_event_t *eventCache_new;
-    const int new_cache_size = computeMaxCacheSizeLocked();
-    // Allocate new cache, copy over events from the old cache & scratch, free up memory.
-    eventCache_new = new sensors_event_t[new_cache_size];
-    memcpy(eventCache_new, mEventCache, mCacheSize * sizeof(sensors_event_t));
-    memcpy(&eventCache_new[mCacheSize], scratch, count * sizeof(sensors_event_t));
-
-    ALOGD_IF(DEBUG_CONNECTIONS, "reAllocateCacheLocked maxCacheSize=%d %d", mMaxCacheSize,
-            new_cache_size);
-
-    delete mEventCache;
-    mEventCache = eventCache_new;
-    mCacheSize += count;
-    mMaxCacheSize = new_cache_size;
-}
-
-void SensorService::SensorEventConnection::sendPendingFlushEventsLocked() {
-    ASensorEvent flushCompleteEvent;
-    memset(&flushCompleteEvent, 0, sizeof(flushCompleteEvent));
-    flushCompleteEvent.type = SENSOR_TYPE_META_DATA;
-    // Loop through all the sensors for this connection and check if there are any pending
-    // flush complete events to be sent.
-    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        FlushInfo& flushInfo = mSensorInfo.editValueAt(i);
-        while (flushInfo.mPendingFlushEventsToSend > 0) {
-            const int sensor_handle = mSensorInfo.keyAt(i);
-            flushCompleteEvent.meta_data.sensor = sensor_handle;
-            bool wakeUpSensor = mService->getSensorFromHandle(sensor_handle).isWakeUpSensor();
-            if (wakeUpSensor) {
-               ++mWakeLockRefCount;
-               flushCompleteEvent.flags |= WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-            }
-            ssize_t size = SensorEventQueue::write(mChannel, &flushCompleteEvent, 1);
-            if (size < 0) {
-                if (wakeUpSensor) --mWakeLockRefCount;
-                return;
-            }
-            ALOGD_IF(DEBUG_CONNECTIONS, "sent dropped flush complete event==%d ",
-                    flushCompleteEvent.meta_data.sensor);
-            flushInfo.mPendingFlushEventsToSend--;
-        }
-    }
-}
-
-void SensorService::SensorEventConnection::writeToSocketFromCache() {
-    // At a time write at most half the size of the receiver buffer in SensorEventQueue OR
-    // half the size of the socket buffer allocated in BitTube whichever is smaller.
-    const int maxWriteSize = helpers::min(SensorEventQueue::MAX_RECEIVE_BUFFER_EVENT_COUNT/2,
-            int(mService->mSocketBufferSize/(sizeof(sensors_event_t)*2)));
-    Mutex::Autolock _l(mConnectionLock);
-    // Send pending flush complete events (if any)
-    sendPendingFlushEventsLocked();
-    for (int numEventsSent = 0; numEventsSent < mCacheSize;) {
-        const int numEventsToWrite = helpers::min(mCacheSize - numEventsSent, maxWriteSize);
-        int index_wake_up_event =
-                  findWakeUpSensorEventLocked(mEventCache + numEventsSent, numEventsToWrite);
-        if (index_wake_up_event >= 0) {
-            mEventCache[index_wake_up_event + numEventsSent].flags |=
-                    WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-            ++mWakeLockRefCount;
-#if DEBUG_CONNECTIONS
-            ++mTotalAcksNeeded;
-#endif
-        }
-
-        ssize_t size = SensorEventQueue::write(mChannel,
-                          reinterpret_cast<ASensorEvent const*>(mEventCache + numEventsSent),
-                          numEventsToWrite);
-        if (size < 0) {
-            if (index_wake_up_event >= 0) {
-                // If there was a wake_up sensor_event, reset the flag.
-                mEventCache[index_wake_up_event + numEventsSent].flags  &=
-                        ~WAKE_UP_SENSOR_EVENT_NEEDS_ACK;
-                if (mWakeLockRefCount > 0) {
-                    --mWakeLockRefCount;
-                }
-#if DEBUG_CONNECTIONS
-                --mTotalAcksNeeded;
-#endif
-            }
-            memmove(mEventCache, &mEventCache[numEventsSent],
-                                 (mCacheSize - numEventsSent) * sizeof(sensors_event_t));
-            ALOGD_IF(DEBUG_CONNECTIONS, "wrote %d events from cache size==%d ",
-                    numEventsSent, mCacheSize);
-            mCacheSize -= numEventsSent;
-            return;
-        }
-        numEventsSent += numEventsToWrite;
-#if DEBUG_CONNECTIONS
-        mEventsSentFromCache += numEventsToWrite;
-#endif
-    }
-    ALOGD_IF(DEBUG_CONNECTIONS, "wrote all events from cache size=%d ", mCacheSize);
-    // All events from the cache have been sent. Reset cache size to zero.
-    mCacheSize = 0;
-    // There are no more events in the cache. We don't need to poll for write on the fd.
-    // Update Looper registration.
-    updateLooperRegistrationLocked(mService->getLooper());
-}
-
-void SensorService::SensorEventConnection::countFlushCompleteEventsLocked(
-                sensors_event_t const* scratch, const int numEventsDropped) {
-    ALOGD_IF(DEBUG_CONNECTIONS, "dropping %d events ", numEventsDropped);
-    // Count flushComplete events in the events that are about to the dropped. These will be sent
-    // separately before the next batch of events.
-    for (int j = 0; j < numEventsDropped; ++j) {
-        if (scratch[j].type == SENSOR_TYPE_META_DATA) {
-            FlushInfo& flushInfo = mSensorInfo.editValueFor(scratch[j].meta_data.sensor);
-            flushInfo.mPendingFlushEventsToSend++;
-            ALOGD_IF(DEBUG_CONNECTIONS, "increment pendingFlushCount %d",
-                     flushInfo.mPendingFlushEventsToSend);
-        }
-    }
-    return;
-}
-
-int SensorService::SensorEventConnection::findWakeUpSensorEventLocked(
-                       sensors_event_t const* scratch, const int count) {
-    for (int i = 0; i < count; ++i) {
-        if (mService->isWakeUpSensorEvent(scratch[i])) {
-            return i;
-        }
-    }
-    return -1;
-}
-
-sp<BitTube> SensorService::SensorEventConnection::getSensorChannel() const
-{
-    return mChannel;
-}
-
-status_t SensorService::SensorEventConnection::enableDisable(
-        int handle, bool enabled, nsecs_t samplingPeriodNs, nsecs_t maxBatchReportLatencyNs,
-        int reservedFlags)
-{
-    status_t err;
-    if (enabled) {
-        err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
-                               reservedFlags, mOpPackageName);
-
-    } else {
-        err = mService->disable(this, handle);
-    }
-    return err;
-}
-
-status_t SensorService::SensorEventConnection::setEventRate(
-        int handle, nsecs_t samplingPeriodNs)
-{
-    return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
-}
-
-status_t  SensorService::SensorEventConnection::flush() {
-    return  mService->flushSensor(this, mOpPackageName);
-}
-
-int SensorService::SensorEventConnection::handleEvent(int fd, int events, void* /*data*/) {
-    if (events & ALOOPER_EVENT_HANGUP || events & ALOOPER_EVENT_ERROR) {
-        {
-            // If the Looper encounters some error, set the flag mDead, reset mWakeLockRefCount,
-            // and remove the fd from Looper. Call checkWakeLockState to know if SensorService
-            // can release the wake-lock.
-            ALOGD_IF(DEBUG_CONNECTIONS, "%p Looper error %d", this, fd);
-            Mutex::Autolock _l(mConnectionLock);
-            mDead = true;
-            mWakeLockRefCount = 0;
-            updateLooperRegistrationLocked(mService->getLooper());
-        }
-        mService->checkWakeLockState();
-        if (mDataInjectionMode) {
-            // If the Looper has encountered some error in data injection mode, reset SensorService
-            // back to normal mode.
-            mService->resetToNormalMode();
-            mDataInjectionMode = false;
-        }
-        return 1;
-    }
-
-    if (events & ALOOPER_EVENT_INPUT) {
-        unsigned char buf[sizeof(sensors_event_t)];
-        ssize_t numBytesRead = ::recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
-        {
-           Mutex::Autolock _l(mConnectionLock);
-           if (numBytesRead == sizeof(sensors_event_t)) {
-               if (!mDataInjectionMode) {
-                   ALOGE("Data injected in normal mode, dropping event"
-                         "package=%s uid=%d", mPackageName.string(), mUid);
-                   // Unregister call backs.
-                   return 0;
-               }
-               SensorDevice& dev(SensorDevice::getInstance());
-               sensors_event_t sensor_event;
-               memset(&sensor_event, 0, sizeof(sensor_event));
-               memcpy(&sensor_event, buf, sizeof(sensors_event_t));
-               Sensor sensor = mService->getSensorFromHandle(sensor_event.sensor);
-               sensor_event.type = sensor.getType();
-               dev.injectSensorData(&sensor_event);
-#if DEBUG_CONNECTIONS
-               ++mEventsReceived;
-#endif
-           } else if (numBytesRead == sizeof(uint32_t)) {
-               uint32_t numAcks = 0;
-               memcpy(&numAcks, buf, numBytesRead);
-               // Sanity check to ensure  there are no read errors in recv, numAcks is always
-               // within the range and not zero. If any of the above don't hold reset
-               // mWakeLockRefCount to zero.
-               if (numAcks > 0 && numAcks < mWakeLockRefCount) {
-                   mWakeLockRefCount -= numAcks;
-               } else {
-                   mWakeLockRefCount = 0;
-               }
-#if DEBUG_CONNECTIONS
-               mTotalAcksReceived += numAcks;
-#endif
-           } else {
-               // Read error, reset wakelock refcount.
-               mWakeLockRefCount = 0;
-           }
-        }
-        // Check if wakelock can be released by sensorservice. mConnectionLock needs to be released
-        // here as checkWakeLockState() will need it.
-        if (mWakeLockRefCount == 0) {
-            mService->checkWakeLockState();
-        }
-        // continue getting callbacks.
-        return 1;
-    }
-
-    if (events & ALOOPER_EVENT_OUTPUT) {
-        // send sensor data that is stored in mEventCache for this connection.
-        mService->sendEventsFromCache(this);
-    }
-    return 1;
-}
-
-int SensorService::SensorEventConnection::computeMaxCacheSizeLocked() const {
-    size_t fifoWakeUpSensors = 0;
-    size_t fifoNonWakeUpSensors = 0;
-    for (size_t i = 0; i < mSensorInfo.size(); ++i) {
-        const Sensor& sensor = mService->getSensorFromHandle(mSensorInfo.keyAt(i));
-        if (sensor.getFifoReservedEventCount() == sensor.getFifoMaxEventCount()) {
-            // Each sensor has a reserved fifo. Sum up the fifo sizes for all wake up sensors and
-            // non wake_up sensors.
-            if (sensor.isWakeUpSensor()) {
-                fifoWakeUpSensors += sensor.getFifoReservedEventCount();
-            } else {
-                fifoNonWakeUpSensors += sensor.getFifoReservedEventCount();
-            }
-        } else {
-            // Shared fifo. Compute the max of the fifo sizes for wake_up and non_wake up sensors.
-            if (sensor.isWakeUpSensor()) {
-                fifoWakeUpSensors = fifoWakeUpSensors > sensor.getFifoMaxEventCount() ?
-                                          fifoWakeUpSensors : sensor.getFifoMaxEventCount();
-
-            } else {
-                fifoNonWakeUpSensors = fifoNonWakeUpSensors > sensor.getFifoMaxEventCount() ?
-                                          fifoNonWakeUpSensors : sensor.getFifoMaxEventCount();
-
-            }
-        }
-   }
-   if (fifoWakeUpSensors + fifoNonWakeUpSensors == 0) {
-       // It is extremely unlikely that there is a write failure in non batch mode. Return a cache
-       // size that is equal to that of the batch mode.
-       // ALOGW("Write failure in non-batch mode");
-       return MAX_SOCKET_BUFFER_SIZE_BATCHED/sizeof(sensors_event_t);
-   }
-   return fifoWakeUpSensors + fifoNonWakeUpSensors;
-}
-
-// ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 9a573ae..0d04478 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -17,71 +17,93 @@
 #ifndef ANDROID_SENSOR_SERVICE_H
 #define ANDROID_SENSOR_SERVICE_H
 
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <utils/Vector.h>
-#include <utils/SortedVector.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/AndroidThreads.h>
-#include <utils/RefBase.h>
-#include <utils/Looper.h>
-#include <utils/String8.h>
+#include "SensorList.h"
+#include "RecentEventLogger.h"
 
 #include <binder/BinderService.h>
-
-#include <gui/Sensor.h>
-#include <gui/BitTube.h>
+#include <cutils/compiler.h>
 #include <gui/ISensorServer.h>
 #include <gui/ISensorEventConnection.h>
+#include <gui/Sensor.h>
 
-#include "SensorInterface.h"
+#include <utils/AndroidThreads.h>
+#include <utils/KeyedVector.h>
+#include <utils/Looper.h>
+#include <utils/SortedVector.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <unordered_map>
+#include <unordered_set>
 
 #if __clang__
-// Clang warns about SensorEventConnection::dump hiding BBinder::dump
-// The cause isn't fixable without changing the API, so let's tell clang
-// this is indeed intentional.
+// Clang warns about SensorEventConnection::dump hiding BBinder::dump. The cause isn't fixable
+// without changing the API, so let's tell clang this is indeed intentional.
 #pragma clang diagnostic ignored "-Woverloaded-virtual"
 #endif
 
 // ---------------------------------------------------------------------------
-
+#define IGNORE_HARDWARE_FUSION  false
 #define DEBUG_CONNECTIONS   false
 // Max size is 100 KB which is enough to accept a batch of about 1000 events.
 #define MAX_SOCKET_BUFFER_SIZE_BATCHED 100 * 1024
 // For older HALs which don't support batching, use a smaller socket buffer size.
 #define SOCKET_BUFFER_SIZE_NON_BATCHED 4 * 1024
 
-#define CIRCULAR_BUF_SIZE 10
 #define SENSOR_REGISTRATIONS_BUF_SIZE 20
 
-struct sensors_poll_device_t;
-struct sensors_module_t;
-
 namespace android {
 // ---------------------------------------------------------------------------
+class SensorInterface;
+using namespace SensorServiceUtil;
 
 class SensorService :
         public BinderService<SensorService>,
         public BnSensorServer,
         protected Thread
 {
+    // nested class/struct for internal use
+    class SensorEventConnection;
+
+public:
+    void cleanupConnection(SensorEventConnection* connection);
+
+    status_t enable(const sp<SensorEventConnection>& connection, int handle,
+                    nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags,
+                    const String16& opPackageName);
+
+    status_t disable(const sp<SensorEventConnection>& connection, int handle);
+
+    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns,
+                          const String16& opPackageName);
+
+    status_t flushSensor(const sp<SensorEventConnection>& connection,
+                         const String16& opPackageName);
+
+private:
     friend class BinderService<SensorService>;
 
+    // nested class/struct for internal use
+    class SensorRecord;
+    class SensorEventAckReceiver;
+    struct SensorRegistrationInfo;
+
     enum Mode {
        // The regular operating mode where any application can register/unregister/call flush on
        // sensors.
        NORMAL = 0,
-       // This mode is only used for testing purposes. Not all HALs support this mode. In this
-       // mode, the HAL ignores the sensor data provided by physical sensors and accepts the data
-       // that is injected from the SensorService as if it were the real sensor data. This mode
-       // is primarily used for testing various algorithms like vendor provided SensorFusion,
-       // Step Counter and Step Detector etc. Typically in this mode, there will be a client
-       // (a SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps
-       // can unregister and register for any sensor that supports injection. Registering to sensors
-       // that do not support injection will give an error.
-       // TODO(aakella) : Allow exactly one client to inject sensor data at a time.
+       // This mode is only used for testing purposes. Not all HALs support this mode. In this mode,
+       // the HAL ignores the sensor data provided by physical sensors and accepts the data that is
+       // injected from the SensorService as if it were the real sensor data. This mode is primarily
+       // used for testing various algorithms like vendor provided SensorFusion, Step Counter and
+       // Step Detector etc. Typically in this mode, there will be a client (a
+       // SensorEventConnection) which will be injecting sensor data into the HAL. Normal apps can
+       // unregister and register for any sensor that supports injection. Registering to sensors
+       // that do not support injection will give an error.  TODO(aakella) : Allow exactly one
+       // client to inject sensor data at a time.
        DATA_INJECTION = 1,
        // This mode is used only for testing sensors. Each sensor can be tested in isolation with
        // the required sampling_rate and maxReportLatency parameters without having to think about
@@ -92,9 +114,8 @@
        // these apps can register/unregister/call flush() on sensors. If SensorService switches to
        // NORMAL mode again, all sensors that were previously registered to are activated with the
        // corresponding paramaters if the application hasn't unregistered for sensors in the mean
-       // time.
-       // NOTE: Non whitelisted app whose sensors were previously deactivated may still receive
-       // events if a whitelisted app requests data from the same sensor.
+       // time.  NOTE: Non whitelisted app whose sensors were previously deactivated may still
+       // receive events if a whitelisted app requests data from the same sensor.
        RESTRICTED = 2
 
       // State Transitions supported.
@@ -104,18 +125,19 @@
       // Shell commands to switch modes in SensorService.
       // 1) Put SensorService in RESTRICTED mode with packageName .cts. If it is already in
       // restricted mode it is treated as a NO_OP (and packageName is NOT changed).
-      // $ adb shell dumpsys sensorservice restrict .cts.
+      //
+      //     $ adb shell dumpsys sensorservice restrict .cts.
       //
       // 2) Put SensorService in DATA_INJECTION mode with packageName .xts. If it is already in
       // data_injection mode it is treated as a NO_OP (and packageName is NOT changed).
-      // $ adb shell dumpsys sensorservice data_injection .xts.
+      //
+      //     $ adb shell dumpsys sensorservice data_injection .xts.
       //
       // 3) Reset sensorservice back to NORMAL mode.
-      // $ adb shell dumpsys sensorservice enable
+      //     $ adb shell dumpsys sensorservice enable
     };
 
     static const char* WAKE_LOCK_NAME;
-
     static char const* getServiceName() ANDROID_API { return "sensorservice"; }
     SensorService() ANDROID_API;
     virtual ~SensorService();
@@ -127,221 +149,26 @@
 
     // ISensorServer interface
     virtual Vector<Sensor> getSensorList(const String16& opPackageName);
-    virtual sp<ISensorEventConnection> createSensorEventConnection(const String8& packageName,
-             int requestedMode, const String16& opPackageName);
+    virtual Vector<Sensor> getDynamicSensorList(const String16& opPackageName);
+    virtual sp<ISensorEventConnection> createSensorEventConnection(
+            const String8& packageName,
+            int requestedMode, const String16& opPackageName);
     virtual int isDataInjectionEnabled();
     virtual status_t dump(int fd, const Vector<String16>& args);
 
-    class SensorEventConnection : public BnSensorEventConnection, public LooperCallback {
-        friend class SensorService;
-        virtual ~SensorEventConnection();
-        virtual void onFirstRef();
-        virtual sp<BitTube> getSensorChannel() const;
-        virtual status_t enableDisable(int handle, bool enabled, nsecs_t samplingPeriodNs,
-                                       nsecs_t maxBatchReportLatencyNs, int reservedFlags);
-        virtual status_t setEventRate(int handle, nsecs_t samplingPeriodNs);
-        virtual status_t flush();
-        // Count the number of flush complete events which are about to be dropped in the buffer.
-        // Increment mPendingFlushEventsToSend in mSensorInfo. These flush complete events will be
-        // sent separately before the next batch of events.
-        void countFlushCompleteEventsLocked(sensors_event_t const* scratch, int numEventsDropped);
-
-        // Check if there are any wake up events in the buffer. If yes, return the index of the
-        // first wake_up sensor event in the buffer else return -1. This wake_up sensor event will
-        // have the flag WAKE_UP_SENSOR_EVENT_NEEDS_ACK set. Exactly one event per packet will have
-        // the wake_up flag set. SOCK_SEQPACKET ensures that either the entire packet is read or
-        // dropped.
-        int findWakeUpSensorEventLocked(sensors_event_t const* scratch, int count);
-
-        // Send pending flush_complete events. There may have been flush_complete_events that are
-        // dropped which need to be sent separately before other events. On older HALs (1_0) this
-        // method emulates the behavior of flush().
-        void sendPendingFlushEventsLocked();
-
-        // Writes events from mEventCache to the socket.
-        void writeToSocketFromCache();
-
-        // Compute the approximate cache size from the FIFO sizes of various sensors registered for
-        // this connection. Wake up and non-wake up sensors have separate FIFOs but FIFO may be
-        // shared amongst wake-up sensors and non-wake up sensors.
-        int computeMaxCacheSizeLocked() const;
-
-        // When more sensors register, the maximum cache size desired may change. Compute max cache
-        // size, reallocate memory and copy over events from the older cache.
-        void reAllocateCacheLocked(sensors_event_t const* scratch, int count);
-
-        // LooperCallback method. If there is data to read on this fd, it is an ack from the
-        // app that it has read events from a wake up sensor, decrement mWakeLockRefCount.
-        // If this fd is available for writing send the data from the cache.
-        virtual int handleEvent(int fd, int events, void* data);
-
-        // Increment mPendingFlushEventsToSend for the given sensor handle.
-        void incrementPendingFlushCount(int32_t handle);
-
-        // Add or remove the file descriptor associated with the BitTube to the looper. If mDead is
-        // set to true or there are no more sensors for this connection, the file descriptor is
-        // removed if it has been previously added to the Looper. Depending on the state of the
-        // connection FD may be added to the Looper. The flags to set are determined by the internal
-        // state of the connection. FDs are added to the looper when wake-up sensors are registered
-        // (to poll for acknowledgements) and when write fails on the socket when there are too many
-        // error and the other end hangs up or when this client unregisters for this connection.
-        void updateLooperRegistration(const sp<Looper>& looper);
-        void updateLooperRegistrationLocked(const sp<Looper>& looper);
-
-        sp<SensorService> const mService;
-        sp<BitTube> mChannel;
-        uid_t mUid;
-        mutable Mutex mConnectionLock;
-        // Number of events from wake up sensors which are still pending and haven't been delivered
-        // to the corresponding application. It is incremented by one unit for each write to the
-        // socket.
-        uint32_t mWakeLockRefCount;
-
-        // If this flag is set to true, it means that the file descriptor associated with the
-        // BitTube has been added to the Looper in SensorService. This flag is typically set when
-        // this connection has wake-up sensors associated with it or when write has failed on this
-        // connection and we're storing some events in the cache.
-        bool mHasLooperCallbacks;
-        // If there are any errors associated with the Looper this flag is set to true and
-        // mWakeLockRefCount is reset to zero. needsWakeLock method will always return false, if
-        // this flag is set.
-        bool mDead;
-
-        bool mDataInjectionMode;
-        struct FlushInfo {
-            // The number of flush complete events dropped for this sensor is stored here.
-            // They are sent separately before the next batch of events.
-            int mPendingFlushEventsToSend;
-            // Every activate is preceded by a flush. Only after the first flush complete is
-            // received, the events for the sensor are sent on that *connection*.
-            bool mFirstFlushPending;
-            FlushInfo() : mPendingFlushEventsToSend(0), mFirstFlushPending(false) {}
-        };
-        // protected by SensorService::mLock. Key for this vector is the sensor handle.
-        KeyedVector<int, FlushInfo> mSensorInfo;
-        sensors_event_t *mEventCache;
-        int mCacheSize, mMaxCacheSize;
-        String8 mPackageName;
-        const String16 mOpPackageName;
-#if DEBUG_CONNECTIONS
-        int mEventsReceived, mEventsSent, mEventsSentFromCache;
-        int mTotalAcksNeeded, mTotalAcksReceived;
-#endif
-
-    public:
-        SensorEventConnection(const sp<SensorService>& service, uid_t uid, String8 packageName,
-                 bool isDataInjectionMode, const String16& opPackageName);
-
-        status_t sendEvents(sensors_event_t const* buffer, size_t count,
-                sensors_event_t* scratch,
-                SensorEventConnection const * const * mapFlushEventsToConnections = NULL);
-        bool hasSensor(int32_t handle) const;
-        bool hasAnySensor() const;
-        bool hasOneShotSensors() const;
-        bool addSensor(int32_t handle);
-        bool removeSensor(int32_t handle);
-        void setFirstFlushPending(int32_t handle, bool value);
-        void dump(String8& result);
-        bool needsWakeLock();
-        void resetWakeLockRefCount();
-        String8 getPackageName() const;
-
-        uid_t getUid() const { return mUid; }
-    };
-
-    class SensorRecord {
-        SortedVector< wp<SensorEventConnection> > mConnections;
-        // A queue of all flush() calls made on this sensor. Flush complete events will be
-        // sent in this order.
-        Vector< wp<SensorEventConnection> > mPendingFlushConnections;
-    public:
-        SensorRecord(const sp<SensorEventConnection>& connection);
-        bool addConnection(const sp<SensorEventConnection>& connection);
-        bool removeConnection(const wp<SensorEventConnection>& connection);
-        size_t getNumConnections() const { return mConnections.size(); }
-
-        void addPendingFlushConnection(const sp<SensorEventConnection>& connection);
-        void removeFirstPendingFlushConnection();
-        SensorEventConnection * getFirstPendingFlushConnection();
-        void clearAllPendingFlushConnections();
-    };
-
-    class SensorEventAckReceiver : public Thread {
-        sp<SensorService> const mService;
-    public:
-        virtual bool threadLoop();
-        SensorEventAckReceiver(const sp<SensorService>& service): mService(service) {}
-    };
-
-    // sensor_event_t with only the data and the timestamp.
-    struct TrimmedSensorEvent {
-        union {
-            float *mData;
-            uint64_t mStepCounter;
-        };
-        // Timestamp from the sensor_event.
-        int64_t mTimestamp;
-        // HH:MM:SS local time at which this sensor event is read at SensorService. Useful
-        // for debugging.
-        int32_t mHour, mMin, mSec;
-
-        TrimmedSensorEvent(int sensorType);
-        static bool isSentinel(const TrimmedSensorEvent& event);
-
-        ~TrimmedSensorEvent() {
-            delete [] mData;
-        }
-    };
-
-    // A circular buffer of TrimmedSensorEvents. The size of this buffer is typically 10. The
-    // last N events generated from the sensor are stored in this buffer. The buffer is NOT
-    // cleared when the sensor unregisters and as a result one may see very old data in the
-    // dumpsys output but this is WAI.
-    class CircularBuffer {
-        int mNextInd;
-        int mSensorType;
-        int mBufSize;
-        TrimmedSensorEvent ** mTrimmedSensorEventArr;
-    public:
-        CircularBuffer(int sensor_event_type);
-        void addEvent(const sensors_event_t& sensor_event);
-        void printBuffer(String8& buffer) const;
-        bool populateLastEvent(sensors_event_t *event);
-        ~CircularBuffer();
-    };
-
-    struct SensorRegistrationInfo {
-        int32_t mSensorHandle;
-        String8 mPackageName;
-        bool mActivated;
-        int32_t mSamplingRateUs;
-        int32_t mMaxReportLatencyUs;
-        int32_t mHour, mMin, mSec;
-
-        SensorRegistrationInfo() : mPackageName() {
-            mSensorHandle = mSamplingRateUs = mMaxReportLatencyUs = INT32_MIN;
-            mHour = mMin = mSec = INT32_MIN;
-            mActivated = false;
-        }
-
-        static bool isSentinel(const SensorRegistrationInfo& info) {
-           return (info.mHour == INT32_MIN && info.mMin == INT32_MIN && info.mSec == INT32_MIN);
-        }
-    };
-
-    static int getNumEventsForSensorType(int sensor_event_type);
     String8 getSensorName(int handle) const;
     bool isVirtualSensor(int handle) const;
-    Sensor getSensorFromHandle(int handle) const;
+    sp<SensorInterface> getSensorInterfaceFromHandle(int handle) const;
     bool isWakeUpSensor(int type) const;
     void recordLastValueLocked(sensors_event_t const* buffer, size_t count);
     static void sortEventBuffer(sensors_event_t* buffer, size_t count);
-    Sensor registerSensor(SensorInterface* sensor);
-    Sensor registerVirtualSensor(SensorInterface* sensor);
-    status_t cleanupWithoutDisable(
-            const sp<SensorEventConnection>& connection, int handle);
-    status_t cleanupWithoutDisableLocked(
-            const sp<SensorEventConnection>& connection, int handle);
+    const Sensor& registerSensor(SensorInterface* sensor,
+                                 bool isDebug = false, bool isVirtual = false);
+    const Sensor& registerVirtualSensor(SensorInterface* sensor, bool isDebug = false);
+    const Sensor& registerDynamicSensorLocked(SensorInterface* sensor, bool isDebug = false);
+    bool unregisterDynamicSensorLocked(int handle);
+    status_t cleanupWithoutDisable(const sp<SensorEventConnection>& connection, int handle);
+    status_t cleanupWithoutDisableLocked(const sp<SensorEventConnection>& connection, int handle);
     void cleanupAutoDisabledSensorLocked(const sp<SensorEventConnection>& connection,
             sensors_event_t const* buffer, const int count);
     static bool canAccessSensor(const Sensor& sensor, const char* operation,
@@ -354,8 +181,6 @@
     bool isWakeLockAcquired();
     bool isWakeUpSensorEvent(const sensors_event_t& event) const;
 
-    SensorRecord * getSensorRecord(int handle);
-
     sp<Looper> getLooper() const;
 
     // Reset mWakeLockRefCounts for all SensorEventConnections to zero. This may happen if
@@ -363,8 +188,8 @@
     // wake_up sensors.
     void resetAllWakeLockRefCounts();
 
-    // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to
-    // 5 seconds and wake the looper.
+    // Acquire or release wake_lock. If wake_lock is acquired, set the timeout in the looper to 5
+    // seconds and wake the looper.
     void setWakeLockAcquiredLocked(bool acquire);
 
     // Send events from the event cache for this particular connection.
@@ -372,7 +197,7 @@
 
     // Promote all weak referecences in mActiveConnections vector to strong references and add them
     // to the output vector.
-    void populateActiveConnections(SortedVector< sp<SensorEventConnection> >* activeConnections);
+    void populateActiveConnections( SortedVector< sp<SensorEventConnection> >* activeConnections);
 
     // If SensorService is operating in RESTRICTED mode, only select whitelisted packages are
     // allowed to register for or call flush on sensors. Typically only cts test packages are
@@ -383,13 +208,9 @@
     status_t resetToNormalMode();
     status_t resetToNormalModeLocked();
 
-    // constants
-    Vector<Sensor> mSensorList;
-    Vector<Sensor> mUserSensorListDebug;
-    Vector<Sensor> mUserSensorList;
-    DefaultKeyedVector<int, SensorInterface*> mSensorMap;
-    Vector<SensorInterface *> mVirtualSensorList;
+    SensorList mSensors;
     status_t mInitCheck;
+
     // Socket buffersize used to initialize BitTube. This size depends on whether batching is
     // supported or not.
     uint32_t mSocketBufferSize;
@@ -399,36 +220,23 @@
     // protected by mLock
     mutable Mutex mLock;
     DefaultKeyedVector<int, SensorRecord*> mActiveSensors;
-    DefaultKeyedVector<int, SensorInterface*> mActiveVirtualSensors;
+    std::unordered_set<int> mActiveVirtualSensors;
     SortedVector< wp<SensorEventConnection> > mActiveConnections;
     bool mWakeLockAcquired;
     sensors_event_t *mSensorEventBuffer, *mSensorEventScratch;
     SensorEventConnection const **mMapFlushEventsToConnections;
+    std::unordered_map<int, RecentEventLogger*> mRecentEvent;
     Mode mCurrentOperatingMode;
+
     // This packagaName is set when SensorService is in RESTRICTED or DATA_INJECTION mode. Only
     // applications with this packageName are allowed to activate/deactivate or call flush on
     // sensors. To run CTS this is can be set to ".cts." and only CTS tests will get access to
     // sensors.
     String8 mWhiteListedPackage;
 
-    // The size of this vector is constant, only the items are mutable
-    KeyedVector<int32_t, CircularBuffer *> mLastEventSeen;
-
     int mNextSensorRegIndex;
     Vector<SensorRegistrationInfo> mLastNSensorRegistrations;
-public:
-    void cleanupConnection(SensorEventConnection* connection);
-    status_t enable(const sp<SensorEventConnection>& connection, int handle,
-                    nsecs_t samplingPeriodNs,  nsecs_t maxBatchReportLatencyNs, int reservedFlags,
-                    const String16& opPackageName);
-    status_t disable(const sp<SensorEventConnection>& connection, int handle);
-    status_t setEventRate(const sp<SensorEventConnection>& connection, int handle, nsecs_t ns,
-                          const String16& opPackageName);
-    status_t flushSensor(const sp<SensorEventConnection>& connection,
-                         const String16& opPackageName);
 };
 
-// ---------------------------------------------------------------------------
-}; // namespace android
-
+} // namespace android
 #endif // ANDROID_SENSOR_SERVICE_H
diff --git a/services/sensorservice/SensorServiceUtils.cpp b/services/sensorservice/SensorServiceUtils.cpp
new file mode 100644
index 0000000..1996a00
--- /dev/null
+++ b/services/sensorservice/SensorServiceUtils.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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 "SensorServiceUtils.h"
+
+#include <hardware/sensors.h>
+
+namespace android {
+namespace SensorServiceUtil {
+
+// Keep in sync with sSensorReportingMode in Sensor.java
+size_t eventSizeBySensorType(int type) {
+    if (type >= SENSOR_TYPE_DEVICE_PRIVATE_BASE) {
+        return 16;
+    }
+    switch (type) {
+        case SENSOR_TYPE_POSE_6DOF:
+            return 16;
+
+        case SENSOR_TYPE_ROTATION_VECTOR:
+        case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+            return 5;
+
+        case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+        case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+            return 6;
+
+        case SENSOR_TYPE_GAME_ROTATION_VECTOR:
+            return 4;
+
+        case SENSOR_TYPE_SIGNIFICANT_MOTION:
+        case SENSOR_TYPE_STEP_DETECTOR:
+        case SENSOR_TYPE_STEP_COUNTER:
+        case SENSOR_TYPE_HEART_RATE:
+        case SENSOR_TYPE_TILT_DETECTOR:
+        case SENSOR_TYPE_WAKE_GESTURE:
+        case SENSOR_TYPE_GLANCE_GESTURE:
+        case SENSOR_TYPE_PICK_UP_GESTURE:
+        case SENSOR_TYPE_WRIST_TILT_GESTURE:
+        case SENSOR_TYPE_DEVICE_ORIENTATION:
+        case SENSOR_TYPE_STATIONARY_DETECT:
+        case SENSOR_TYPE_MOTION_DETECT:
+        case SENSOR_TYPE_HEART_BEAT:
+            return 1;
+
+        default:
+            return 3;
+    }
+}
+
+} // namespace SensorServiceUtil
+} // namespace android;
diff --git a/services/sensorservice/SensorServiceUtils.h b/services/sensorservice/SensorServiceUtils.h
new file mode 100644
index 0000000..1558feb
--- /dev/null
+++ b/services/sensorservice/SensorServiceUtils.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_SERVICE_UTIL
+#define ANDROID_SENSOR_SERVICE_UTIL
+
+#include <cstddef>
+#include <string>
+
+namespace android {
+namespace SensorServiceUtil {
+
+class Dumpable {
+public:
+    virtual std::string dump() const = 0;
+    virtual void setFormat(std::string ) {}
+    virtual ~Dumpable() {}
+};
+
+size_t eventSizeBySensorType(int type);
+
+} // namespace SensorServiceUtil
+} // namespace android;
+
+#endif // ANDROID_SENSOR_SERVICE_UTIL
diff --git a/services/sensorservice/main_sensorservice.cpp b/services/sensorservice/main_sensorservice.cpp
index 0a96f42..01bb0e7 100644
--- a/services/sensorservice/main_sensorservice.cpp
+++ b/services/sensorservice/main_sensorservice.cpp
@@ -20,6 +20,7 @@
 using namespace android;
 
 int main(int /*argc*/, char** /*argv*/) {
+    signal(SIGPIPE, SIG_IGN);
     SensorService::publishAndJoinThreadPool();
     return 0;
 }
diff --git a/services/sensorservice/tests/sensorservicetest.cpp b/services/sensorservice/tests/sensorservicetest.cpp
index cfdf6a3..186b60c 100644
--- a/services/sensorservice/tests/sensorservicetest.cpp
+++ b/services/sensorservice/tests/sensorservicetest.cpp
@@ -62,7 +62,7 @@
 
 int main()
 {
-    SensorManager mgr(String16("Sensor Service Test"));
+    SensorManager& mgr = SensorManager::getInstanceForPackage(String16("Sensor Service Test"));
 
     Sensor const* const* list;
     ssize_t count = mgr.getSensorList(&list);
diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h
index 24f30ff..a142bad 100644
--- a/services/sensorservice/vec.h
+++ b/services/sensorservice/vec.h
@@ -37,7 +37,7 @@
 class vec;
 
 template <typename TYPE, size_t SIZE>
-class vbase;
+struct vbase;
 
 namespace helpers {
 
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 1901ef9..fb6307e 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -10,16 +10,18 @@
     DispSync.cpp \
     EventControlThread.cpp \
     EventThread.cpp \
+    FenceTracker.cpp \
     FrameTracker.cpp \
+    GpuService.cpp \
     Layer.cpp \
     LayerDim.cpp \
     MessageQueue.cpp \
     MonitoredProducer.cpp \
-    SurfaceFlinger.cpp \
     SurfaceFlingerConsumer.cpp \
     Transform.cpp \
     DisplayHardware/FramebufferSurface.cpp \
-    DisplayHardware/HWComposer.cpp \
+    DisplayHardware/HWC2.cpp \
+    DisplayHardware/HWC2On1Adapter.cpp \
     DisplayHardware/PowerHAL.cpp \
     DisplayHardware/VirtualDisplaySurface.cpp \
     Effects/Daltonizer.cpp \
@@ -36,9 +38,25 @@
     RenderEngine/GLES11RenderEngine.cpp \
     RenderEngine/GLES20RenderEngine.cpp
 
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include \
+	external/vulkan-validation-layers/libs/vkjson
 
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
+#LOCAL_CFLAGS += -DENABLE_FENCE_TRACKING
+
+USE_HWC2 := false
+ifeq ($(USE_HWC2),true)
+    LOCAL_CFLAGS += -DUSE_HWC2
+    LOCAL_SRC_FILES += \
+        SurfaceFlinger.cpp \
+        DisplayHardware/HWComposer.cpp
+else
+    LOCAL_SRC_FILES += \
+        SurfaceFlinger_hwc1.cpp \
+        DisplayHardware/HWComposer_hwc1.cpp
+endif
 
 ifeq ($(TARGET_BOARD_PLATFORM),omap4)
     LOCAL_CFLAGS += -DHAS_CONTEXT_PRIORITY
@@ -90,8 +108,9 @@
 endif
 
 LOCAL_CFLAGS += -fvisibility=hidden -Werror=format
-LOCAL_CFLAGS += -std=c++11
+LOCAL_CFLAGS += -std=c++14
 
+LOCAL_STATIC_LIBRARIES := libvkjson
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     liblog \
@@ -104,7 +123,8 @@
     libbinder \
     libui \
     libgui \
-    libpowermanager
+    libpowermanager \
+    libvulkan
 
 LOCAL_MODULE := libsurfaceflinger
 
@@ -120,7 +140,9 @@
 
 LOCAL_LDFLAGS := -Wl,--version-script,art/sigchainlib/version-script.txt -Wl,--export-dynamic
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_CPPFLAGS := -std=c++11
+LOCAL_CPPFLAGS := -std=c++14
+
+LOCAL_INIT_RC := surfaceflinger.rc
 
 ifneq ($(ENABLE_CPUSETS),)
     LOCAL_CFLAGS += -DENABLE_CPUSETS
@@ -157,7 +179,7 @@
 LOCAL_CLANG := true
 
 LOCAL_CFLAGS := -DLOG_TAG=\"SurfaceFlinger\"
-LOCAL_CPPFLAGS := -std=c++11
+LOCAL_CPPFLAGS := -std=c++14
 
 LOCAL_SRC_FILES := \
     DdmConnection.cpp
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 49389e0..2a025b8 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -134,7 +134,7 @@
                 sp<IBinder>* handle,
                 sp<IGraphicBufferProducer>* gbp)
             : flinger(flinger), client(client),
-              handle(handle), gbp(gbp),
+              handle(handle), gbp(gbp), result(NO_ERROR),
               name(name), w(w), h(h), format(format), flags(flags) {
         }
         status_t getResult() const { return result; }
diff --git a/services/surfaceflinger/DispSync.cpp b/services/surfaceflinger/DispSync.cpp
index 3738a55..37b6420 100644
--- a/services/surfaceflinger/DispSync.cpp
+++ b/services/surfaceflinger/DispSync.cpp
@@ -15,6 +15,7 @@
  */
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
+//#define LOG_NDEBUG 0
 
 // This is needed for stdint.h to define INT64_MAX in C++
 #define __STDC_LIMIT_MACROS
@@ -33,12 +34,21 @@
 #include "DispSync.h"
 #include "EventLog/EventLog.h"
 
+#include <algorithm>
+
+using std::max;
+using std::min;
+
 namespace android {
 
 // Setting this to true enables verbose tracing that can be used to debug
 // vsync event model or phase issues.
 static const bool kTraceDetailedInfo = false;
 
+// Setting this to true adds a zero-phase tracer for correlating with hardware
+// vsync events
+static const bool kEnableZeroPhaseTracer = false;
+
 // This is the threshold used to determine when hardware vsync events are
 // needed to re-synchronize the software vsync model with the hardware.  The
 // error metric used is the mean of the squared difference between each
@@ -49,26 +59,36 @@
 // vsync event.
 static const int64_t kPresentTimeOffset = PRESENT_TIME_OFFSET_FROM_VSYNC_NS;
 
+#undef LOG_TAG
+#define LOG_TAG "DispSyncThread"
 class DispSyncThread: public Thread {
 public:
 
-    DispSyncThread():
+    DispSyncThread(const char* name):
+            mName(name),
             mStop(false),
             mPeriod(0),
             mPhase(0),
-            mWakeupLatency(0) {
-    }
+            mReferenceTime(0),
+            mWakeupLatency(0),
+            mFrameNumber(0) {}
 
     virtual ~DispSyncThread() {}
 
-    void updateModel(nsecs_t period, nsecs_t phase) {
+    void updateModel(nsecs_t period, nsecs_t phase, nsecs_t referenceTime) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
         mPeriod = period;
         mPhase = phase;
+        mReferenceTime = referenceTime;
+        ALOGV("[%s] updateModel: mPeriod = %" PRId64 ", mPhase = %" PRId64
+                " mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+                ns2us(mPhase), ns2us(mReferenceTime));
         mCond.signal();
     }
 
     void stop() {
+        if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
         mStop = true;
         mCond.signal();
@@ -77,7 +97,6 @@
     virtual bool threadLoop() {
         status_t err;
         nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-        nsecs_t nextEventTime = 0;
 
         while (true) {
             Vector<CallbackInvocation> callbackInvocations;
@@ -87,6 +106,12 @@
             { // Scope for lock
                 Mutex::Autolock lock(mMutex);
 
+                if (kTraceDetailedInfo) {
+                    ATRACE_INT64("DispSync:Frame", mFrameNumber);
+                }
+                ALOGV("[%s] Frame %" PRId64, mName, mFrameNumber);
+                ++mFrameNumber;
+
                 if (mStop) {
                     return false;
                 }
@@ -101,13 +126,21 @@
                     continue;
                 }
 
-                nextEventTime = computeNextEventTimeLocked(now);
-                targetTime = nextEventTime;
+                targetTime = computeNextEventTimeLocked(now);
 
                 bool isWakeup = false;
 
                 if (now < targetTime) {
-                    err = mCond.waitRelative(mMutex, targetTime - now);
+                    if (kTraceDetailedInfo) ATRACE_NAME("DispSync waiting");
+
+                    if (targetTime == INT64_MAX) {
+                        ALOGV("[%s] Waiting forever", mName);
+                        err = mCond.wait(mMutex);
+                    } else {
+                        ALOGV("[%s] Waiting until %" PRId64, mName,
+                                ns2us(targetTime));
+                        err = mCond.waitRelative(mMutex, targetTime - now);
+                    }
 
                     if (err == TIMED_OUT) {
                         isWakeup = true;
@@ -120,15 +153,15 @@
 
                 now = systemTime(SYSTEM_TIME_MONOTONIC);
 
+                // Don't correct by more than 1.5 ms
+                static const nsecs_t kMaxWakeupLatency = us2ns(1500);
+
                 if (isWakeup) {
                     mWakeupLatency = ((mWakeupLatency * 63) +
                             (now - targetTime)) / 64;
-                    if (mWakeupLatency > 500000) {
-                        // Don't correct by more than 500 us
-                        mWakeupLatency = 500000;
-                    }
+                    mWakeupLatency = min(mWakeupLatency, kMaxWakeupLatency);
                     if (kTraceDetailedInfo) {
-                        ATRACE_INT64("DispSync:WakeupLat", now - nextEventTime);
+                        ATRACE_INT64("DispSync:WakeupLat", now - targetTime);
                         ATRACE_INT64("DispSync:AvgWakeupLat", mWakeupLatency);
                     }
                 }
@@ -144,7 +177,9 @@
         return false;
     }
 
-    status_t addEventListener(nsecs_t phase, const sp<DispSync::Callback>& callback) {
+    status_t addEventListener(const char* name, nsecs_t phase,
+            const sp<DispSync::Callback>& callback) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
 
         for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -154,15 +189,14 @@
         }
 
         EventListener listener;
+        listener.mName = name;
         listener.mPhase = phase;
         listener.mCallback = callback;
 
         // We want to allow the firstmost future event to fire without
-        // allowing any past events to fire.  Because
-        // computeListenerNextEventTimeLocked filters out events within a half
-        // a period of the last event time, we need to initialize the last
-        // event time to a half a period in the past.
-        listener.mLastEventTime = systemTime(SYSTEM_TIME_MONOTONIC) - mPeriod / 2;
+        // allowing any past events to fire
+        listener.mLastEventTime = systemTime() - mPeriod / 2 + mPhase -
+                mWakeupLatency;
 
         mEventListeners.push(listener);
 
@@ -172,6 +206,7 @@
     }
 
     status_t removeEventListener(const sp<DispSync::Callback>& callback) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
 
         for (size_t i = 0; i < mEventListeners.size(); i++) {
@@ -187,6 +222,7 @@
 
     // This method is only here to handle the kIgnorePresentFences case.
     bool hasAnyEventListeners() {
+        if (kTraceDetailedInfo) ATRACE_CALL();
         Mutex::Autolock lock(mMutex);
         return !mEventListeners.empty();
     }
@@ -194,6 +230,7 @@
 private:
 
     struct EventListener {
+        const char* mName;
         nsecs_t mPhase;
         nsecs_t mLastEventTime;
         sp<DispSync::Callback> mCallback;
@@ -205,6 +242,8 @@
     };
 
     nsecs_t computeNextEventTimeLocked(nsecs_t now) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        ALOGV("[%s] computeNextEventTimeLocked", mName);
         nsecs_t nextEventTime = INT64_MAX;
         for (size_t i = 0; i < mEventListeners.size(); i++) {
             nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
@@ -215,21 +254,28 @@
             }
         }
 
+        ALOGV("[%s] nextEventTime = %" PRId64, mName, ns2us(nextEventTime));
         return nextEventTime;
     }
 
     Vector<CallbackInvocation> gatherCallbackInvocationsLocked(nsecs_t now) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        ALOGV("[%s] gatherCallbackInvocationsLocked @ %" PRId64, mName,
+                ns2us(now));
+
         Vector<CallbackInvocation> callbackInvocations;
-        nsecs_t ref = now - mPeriod;
+        nsecs_t onePeriodAgo = now - mPeriod;
 
         for (size_t i = 0; i < mEventListeners.size(); i++) {
             nsecs_t t = computeListenerNextEventTimeLocked(mEventListeners[i],
-                    ref);
+                    onePeriodAgo);
 
             if (t < now) {
                 CallbackInvocation ci;
                 ci.mCallback = mEventListeners[i].mCallback;
                 ci.mEventTime = t;
+                ALOGV("[%s] [%s] Preparing to fire", mName,
+                        mEventListeners[i].mName);
                 callbackInvocations.push(ci);
                 mEventListeners.editItemAt(i).mLastEventTime = t;
             }
@@ -239,41 +285,85 @@
     }
 
     nsecs_t computeListenerNextEventTimeLocked(const EventListener& listener,
-            nsecs_t ref) {
+            nsecs_t baseTime) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
+        ALOGV("[%s] [%s] computeListenerNextEventTimeLocked(%" PRId64 ")",
+                mName, listener.mName, ns2us(baseTime));
 
-        nsecs_t lastEventTime = listener.mLastEventTime;
-        if (ref < lastEventTime) {
-            ref = lastEventTime;
+        nsecs_t lastEventTime = listener.mLastEventTime + mWakeupLatency;
+        ALOGV("[%s] lastEventTime: %" PRId64, mName, ns2us(lastEventTime));
+        if (baseTime < lastEventTime) {
+            baseTime = lastEventTime;
+            ALOGV("[%s] Clamping baseTime to lastEventTime -> %" PRId64, mName,
+                    ns2us(baseTime));
         }
 
+        baseTime -= mReferenceTime;
+        ALOGV("[%s] Relative baseTime = %" PRId64, mName, ns2us(baseTime));
         nsecs_t phase = mPhase + listener.mPhase;
-        nsecs_t t = (((ref - phase) / mPeriod) + 1) * mPeriod + phase;
+        ALOGV("[%s] Phase = %" PRId64, mName, ns2us(phase));
+        baseTime -= phase;
+        ALOGV("[%s] baseTime - phase = %" PRId64, mName, ns2us(baseTime));
 
-        if (t - listener.mLastEventTime < mPeriod / 2) {
-            t += mPeriod;
+        // If our previous time is before the reference (because the reference
+        // has since been updated), the division by mPeriod will truncate
+        // towards zero instead of computing the floor. Since in all cases
+        // before the reference we want the next time to be effectively now, we
+        // set baseTime to -mPeriod so that numPeriods will be -1.
+        // When we add 1 and the phase, we will be at the correct event time for
+        // this period.
+        if (baseTime < 0) {
+            ALOGV("[%s] Correcting negative baseTime", mName);
+            baseTime = -mPeriod;
         }
 
+        nsecs_t numPeriods = baseTime / mPeriod;
+        ALOGV("[%s] numPeriods = %" PRId64, mName, numPeriods);
+        nsecs_t t = (numPeriods + 1) * mPeriod + phase;
+        ALOGV("[%s] t = %" PRId64, mName, ns2us(t));
+        t += mReferenceTime;
+        ALOGV("[%s] Absolute t = %" PRId64, mName, ns2us(t));
+
+        // Check that it's been slightly more than half a period since the last
+        // event so that we don't accidentally fall into double-rate vsyncs
+        if (t - listener.mLastEventTime < (3 * mPeriod / 5)) {
+            t += mPeriod;
+            ALOGV("[%s] Modifying t -> %" PRId64, mName, ns2us(t));
+        }
+
+        t -= mWakeupLatency;
+        ALOGV("[%s] Corrected for wakeup latency -> %" PRId64, mName, ns2us(t));
+
         return t;
     }
 
     void fireCallbackInvocations(const Vector<CallbackInvocation>& callbacks) {
+        if (kTraceDetailedInfo) ATRACE_CALL();
         for (size_t i = 0; i < callbacks.size(); i++) {
             callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);
         }
     }
 
+    const char* const mName;
+
     bool mStop;
 
     nsecs_t mPeriod;
     nsecs_t mPhase;
+    nsecs_t mReferenceTime;
     nsecs_t mWakeupLatency;
 
+    int64_t mFrameNumber;
+
     Vector<EventListener> mEventListeners;
 
     Mutex mMutex;
     Condition mCond;
 };
 
+#undef LOG_TAG
+#define LOG_TAG "DispSync"
+
 class ZeroPhaseTracer : public DispSync::Callback {
 public:
     ZeroPhaseTracer() : mParity(false) {}
@@ -287,9 +377,10 @@
     bool mParity;
 };
 
-DispSync::DispSync() :
+DispSync::DispSync(const char* name) :
+        mName(name),
         mRefreshSkipCount(0),
-        mThread(new DispSyncThread()) {
+        mThread(new DispSyncThread(name)) {
 
     mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
 
@@ -302,8 +393,8 @@
         // Even if we're just ignoring the fences, the zero-phase tracing is
         // not needed because any time there is an event registered we will
         // turn on the HW vsync events.
-        if (!kIgnorePresentFences) {
-            addEventListener(0, new ZeroPhaseTracer());
+        if (!kIgnorePresentFences && kEnableZeroPhaseTracer) {
+            addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer());
         }
     }
 }
@@ -313,6 +404,9 @@
 void DispSync::reset() {
     Mutex::Autolock lock(mMutex);
 
+    mPhase = 0;
+    mReferenceTime = 0;
+    mModelUpdated = false;
     mNumResyncSamples = 0;
     mFirstResyncSample = 0;
     mNumResyncSamplesSincePresent = 0;
@@ -340,20 +434,31 @@
 
     updateErrorLocked();
 
-    return mPeriod == 0 || mError > kErrorThreshold;
+    return !mModelUpdated || mError > kErrorThreshold;
 }
 
 void DispSync::beginResync() {
     Mutex::Autolock lock(mMutex);
-
+    ALOGV("[%s] beginResync", mName);
+    mModelUpdated = false;
     mNumResyncSamples = 0;
 }
 
 bool DispSync::addResyncSample(nsecs_t timestamp) {
     Mutex::Autolock lock(mMutex);
 
+    ALOGV("[%s] addResyncSample(%" PRId64 ")", mName, ns2us(timestamp));
+
     size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES;
     mResyncSamples[idx] = timestamp;
+    if (mNumResyncSamples == 0) {
+        mPhase = 0;
+        mReferenceTime = timestamp;
+        ALOGV("[%s] First resync sample: mPeriod = %" PRId64 ", mPhase = 0, "
+                "mReferenceTime = %" PRId64, mName, ns2us(mPeriod),
+                ns2us(mReferenceTime));
+        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+    }
 
     if (mNumResyncSamples < MAX_RESYNC_SAMPLES) {
         mNumResyncSamples++;
@@ -376,17 +481,21 @@
         return mThread->hasAnyEventListeners();
     }
 
-    return mPeriod == 0 || mError > kErrorThreshold;
+    // Check against kErrorThreshold / 2 to add some hysteresis before having to
+    // resync again
+    bool modelLocked = mModelUpdated && mError < (kErrorThreshold / 2);
+    ALOGV("[%s] addResyncSample returning %s", mName,
+            modelLocked ? "locked" : "unlocked");
+    return !modelLocked;
 }
 
 void DispSync::endResync() {
 }
 
-status_t DispSync::addEventListener(nsecs_t phase,
+status_t DispSync::addEventListener(const char* name, nsecs_t phase,
         const sp<Callback>& callback) {
-
     Mutex::Autolock lock(mMutex);
-    return mThread->addEventListener(phase, callback);
+    return mThread->addEventListener(name, phase, callback);
 }
 
 void DispSync::setRefreshSkipCount(int count) {
@@ -405,7 +514,8 @@
     Mutex::Autolock lock(mMutex);
     mPeriod = period;
     mPhase = 0;
-    mThread->updateModel(mPeriod, mPhase);
+    mReferenceTime = 0;
+    mThread->updateModel(mPeriod, mPhase, mReferenceTime);
 }
 
 nsecs_t DispSync::getPeriod() {
@@ -415,50 +525,66 @@
 }
 
 void DispSync::updateModelLocked() {
+    ALOGV("[%s] updateModelLocked %zu", mName, mNumResyncSamples);
     if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) {
+        ALOGV("[%s] Computing...", mName);
         nsecs_t durationSum = 0;
+        nsecs_t minDuration = INT64_MAX;
+        nsecs_t maxDuration = 0;
         for (size_t i = 1; i < mNumResyncSamples; i++) {
             size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
             size_t prev = (idx + MAX_RESYNC_SAMPLES - 1) % MAX_RESYNC_SAMPLES;
-            durationSum += mResyncSamples[idx] - mResyncSamples[prev];
+            nsecs_t duration = mResyncSamples[idx] - mResyncSamples[prev];
+            durationSum += duration;
+            minDuration = min(minDuration, duration);
+            maxDuration = max(maxDuration, duration);
         }
 
-        mPeriod = durationSum / (mNumResyncSamples - 1);
+        // Exclude the min and max from the average
+        durationSum -= minDuration + maxDuration;
+        mPeriod = durationSum / (mNumResyncSamples - 3);
+
+        ALOGV("[%s] mPeriod = %" PRId64, mName, ns2us(mPeriod));
 
         double sampleAvgX = 0;
         double sampleAvgY = 0;
         double scale = 2.0 * M_PI / double(mPeriod);
-        for (size_t i = 0; i < mNumResyncSamples; i++) {
+        // Intentionally skip the first sample
+        for (size_t i = 1; i < mNumResyncSamples; i++) {
             size_t idx = (mFirstResyncSample + i) % MAX_RESYNC_SAMPLES;
-            nsecs_t sample = mResyncSamples[idx];
+            nsecs_t sample = mResyncSamples[idx] - mReferenceTime;
             double samplePhase = double(sample % mPeriod) * scale;
             sampleAvgX += cos(samplePhase);
             sampleAvgY += sin(samplePhase);
         }
 
-        sampleAvgX /= double(mNumResyncSamples);
-        sampleAvgY /= double(mNumResyncSamples);
+        sampleAvgX /= double(mNumResyncSamples - 1);
+        sampleAvgY /= double(mNumResyncSamples - 1);
 
         mPhase = nsecs_t(atan2(sampleAvgY, sampleAvgX) / scale);
 
-        if (mPhase < 0) {
+        ALOGV("[%s] mPhase = %" PRId64, mName, ns2us(mPhase));
+
+        if (mPhase < -(mPeriod / 2)) {
             mPhase += mPeriod;
+            ALOGV("[%s] Adjusting mPhase -> %" PRId64, mName, ns2us(mPhase));
         }
 
         if (kTraceDetailedInfo) {
             ATRACE_INT64("DispSync:Period", mPeriod);
-            ATRACE_INT64("DispSync:Phase", mPhase);
+            ATRACE_INT64("DispSync:Phase", mPhase + mPeriod / 2);
         }
 
         // Artificially inflate the period if requested.
         mPeriod += mPeriod * mRefreshSkipCount;
 
-        mThread->updateModel(mPeriod, mPhase);
+        mThread->updateModel(mPeriod, mPhase, mReferenceTime);
+        mModelUpdated = true;
     }
 }
 
 void DispSync::updateErrorLocked() {
-    if (mPeriod == 0) {
+    if (!mModelUpdated) {
         return;
     }
 
@@ -470,7 +596,7 @@
     nsecs_t sqErrSum = 0;
 
     for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
-        nsecs_t sample = mPresentTimes[i];
+        nsecs_t sample = mPresentTimes[i] - mReferenceTime;
         if (sample > mPhase) {
             nsecs_t sampleErr = (sample - mPhase) % period;
             if (sampleErr > period / 2) {
@@ -504,7 +630,8 @@
 nsecs_t DispSync::computeNextRefresh(int periodOffset) const {
     Mutex::Autolock lock(mMutex);
     nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
-    return (((now - mPhase) / mPeriod) + periodOffset + 1) * mPeriod + mPhase;
+    nsecs_t phase = mReferenceTime + mPhase;
+    return (((now - phase) / mPeriod) + periodOffset + 1) * mPeriod + phase;
 }
 
 void DispSync::dump(String8& result) const {
diff --git a/services/surfaceflinger/DispSync.h b/services/surfaceflinger/DispSync.h
index 67142b6..537c81b 100644
--- a/services/surfaceflinger/DispSync.h
+++ b/services/surfaceflinger/DispSync.h
@@ -26,11 +26,8 @@
 namespace android {
 
 // Ignore present (retire) fences if the device doesn't have support for the
-// sync framework, or if all phase offsets are zero.  The latter is useful
-// because it allows us to avoid resync bursts on devices that don't need
-// phase-offset VSYNC events.
-#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK) || \
-        (VSYNC_EVENT_PHASE_OFFSET_NS == 0 && SF_VSYNC_EVENT_PHASE_OFFSET_NS == 0)
+// sync framework
+#if defined(RUNNING_WITHOUT_SYNC_FRAMEWORK)
 static const bool kIgnorePresentFences = true;
 #else
 static const bool kIgnorePresentFences = false;
@@ -64,7 +61,7 @@
         virtual void onDispSyncEvent(nsecs_t when) = 0;
     };
 
-    DispSync();
+    DispSync(const char* name);
     ~DispSync();
 
     // reset clears the resync samples and error value.
@@ -114,7 +111,8 @@
     // given phase offset from the hardware vsync events.  The callback is
     // called from a separate thread and it should return reasonably quickly
     // (i.e. within a few hundred microseconds).
-    status_t addEventListener(nsecs_t phase, const sp<Callback>& callback);
+    status_t addEventListener(const char* name, nsecs_t phase,
+            const sp<Callback>& callback);
 
     // removeEventListener removes an already-registered event callback.  Once
     // this method returns that callback will no longer be called by the
@@ -137,10 +135,12 @@
     void resetErrorLocked();
 
     enum { MAX_RESYNC_SAMPLES = 32 };
-    enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 3 };
+    enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
     enum { NUM_PRESENT_SAMPLES = 8 };
     enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
 
+    const char* const mName;
+
     // mPeriod is the computed period of the modeled vsync events in
     // nanoseconds.
     nsecs_t mPeriod;
@@ -149,11 +149,18 @@
     // number of nanoseconds from time 0 to the first vsync event.
     nsecs_t mPhase;
 
+    // mReferenceTime is the reference time of the modeled vsync events.
+    // It is the nanosecond timestamp of the first vsync event after a resync.
+    nsecs_t mReferenceTime;
+
     // mError is the computed model error.  It is based on the difference
     // between the estimated vsync event times and those observed in the
     // mPresentTimes array.
     nsecs_t mError;
 
+    // Whether we have updated the vsync event model since the last resync.
+    bool mModelUpdated;
+
     // These member variables are the state used during the resynchronization
     // process to store information about the hardware vsync event times used
     // to compute the model.
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 13d44f3..a67b3ff 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "DisplayDevice"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -33,6 +37,9 @@
 
 #include "DisplayHardware/DisplaySurface.h"
 #include "DisplayHardware/HWComposer.h"
+#ifdef USE_HWC2
+#include "DisplayHardware/HWC2.h"
+#endif
 #include "RenderEngine/RenderEngine.h"
 
 #include "clz.h"
@@ -61,11 +68,15 @@
  *
  */
 
+uint32_t DisplayDevice::sPrimaryDisplayOrientation = 0;
+
 DisplayDevice::DisplayDevice(
         const sp<SurfaceFlinger>& flinger,
         DisplayType type,
         int32_t hwcId,
+#ifndef USE_HWC2
         int format,
+#endif
         bool isSecure,
         const wp<IBinder>& displayToken,
         const sp<DisplaySurface>& displaySurface,
@@ -73,36 +84,45 @@
         EGLConfig config)
     : lastCompositionHadVisibleLayers(false),
       mFlinger(flinger),
-      mType(type), mHwcDisplayId(hwcId),
+      mType(type),
+      mHwcDisplayId(hwcId),
       mDisplayToken(displayToken),
       mDisplaySurface(displaySurface),
       mDisplay(EGL_NO_DISPLAY),
       mSurface(EGL_NO_SURFACE),
-      mDisplayWidth(), mDisplayHeight(), mFormat(),
+      mDisplayWidth(),
+      mDisplayHeight(),
+#ifndef USE_HWC2
+      mFormat(),
+#endif
       mFlags(),
       mPageFlipCount(),
       mIsSecure(isSecure),
-      mSecureLayerVisible(false),
       mLayerStack(NO_LAYER_STACK),
       mOrientation(),
       mPowerMode(HWC_POWER_MODE_OFF),
       mActiveConfig(0)
 {
-    mNativeWindow = new Surface(producer, false);
+    Surface* surface;
+    mNativeWindow = surface = new Surface(producer, false);
     ANativeWindow* const window = mNativeWindow.get();
 
     /*
      * Create our display's surface
      */
 
-    EGLSurface surface;
+    EGLSurface eglSurface;
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     if (config == EGL_NO_CONFIG) {
+#ifdef USE_HWC2
+        config = RenderEngine::chooseEglConfig(display, PIXEL_FORMAT_RGBA_8888);
+#else
         config = RenderEngine::chooseEglConfig(display, format);
+#endif
     }
-    surface = eglCreateWindowSurface(display, config, window, NULL);
-    eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
+    eglSurface = eglCreateWindowSurface(display, config, window, NULL);
+    eglQuerySurface(display, eglSurface, EGL_WIDTH,  &mDisplayWidth);
+    eglQuerySurface(display, eglSurface, EGL_HEIGHT, &mDisplayHeight);
 
     // Make sure that composition can never be stalled by a virtual display
     // consumer that isn't processing buffers fast enough. We have to do this
@@ -116,8 +136,10 @@
 
     mConfig = config;
     mDisplay = display;
-    mSurface = surface;
-    mFormat  = format;
+    mSurface = eglSurface;
+#ifndef USE_HWC2
+    mFormat = format;
+#endif
     mPageFlipCount = 0;
     mViewport.makeInvalid();
     mFrame.makeInvalid();
@@ -142,6 +164,10 @@
 
     // initialize the display orientation transform.
     setProjection(DisplayState::eOrientationDefault, mViewport, mFrame);
+
+#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
+    surface->allocateBuffers();
+#endif
 }
 
 DisplayDevice::~DisplayDevice() {
@@ -154,8 +180,10 @@
 void DisplayDevice::disconnect(HWComposer& hwc) {
     if (mHwcDisplayId >= 0) {
         hwc.disconnectDisplay(mHwcDisplayId);
+#ifndef USE_HWC2
         if (mHwcDisplayId >= DISPLAY_VIRTUAL)
             hwc.freeDisplayId(mHwcDisplayId);
+#endif
         mHwcDisplayId = -1;
     }
 }
@@ -172,9 +200,11 @@
     return mDisplayHeight;
 }
 
+#ifndef USE_HWC2
 PixelFormat DisplayDevice::getFormat() const {
     return mFormat;
 }
+#endif
 
 EGLSurface DisplayDevice::getEGLSurface() const {
     return mSurface;
@@ -191,9 +221,11 @@
     return mPageFlipCount;
 }
 
+#ifndef USE_HWC2
 status_t DisplayDevice::compositionComplete() const {
     return mDisplaySurface->compositionComplete();
 }
+#endif
 
 void DisplayDevice::flip(const Region& dirty) const
 {
@@ -215,6 +247,31 @@
     return mDisplaySurface->beginFrame(mustRecompose);
 }
 
+#ifdef USE_HWC2
+status_t DisplayDevice::prepareFrame(HWComposer& hwc) {
+    status_t error = hwc.prepare(*this);
+    if (error != NO_ERROR) {
+        return error;
+    }
+
+    DisplaySurface::CompositionType compositionType;
+    bool hasClient = hwc.hasClientComposition(mHwcDisplayId);
+    bool hasDevice = hwc.hasDeviceComposition(mHwcDisplayId);
+    if (hasClient && hasDevice) {
+        compositionType = DisplaySurface::COMPOSITION_MIXED;
+    } else if (hasClient) {
+        compositionType = DisplaySurface::COMPOSITION_GLES;
+    } else if (hasDevice) {
+        compositionType = DisplaySurface::COMPOSITION_HWC;
+    } else {
+        // Nothing to do -- when turning the screen off we get a frame like
+        // this. Call it a HWC frame since we won't be doing any GLES work but
+        // will do a prepare/set cycle.
+        compositionType = DisplaySurface::COMPOSITION_HWC;
+    }
+    return mDisplaySurface->prepareFrame(compositionType);
+}
+#else
 status_t DisplayDevice::prepareFrame(const HWComposer& hwc) const {
     DisplaySurface::CompositionType compositionType;
     bool haveGles = hwc.hasGlesComposition(mHwcDisplayId);
@@ -233,8 +290,12 @@
     }
     return mDisplaySurface->prepareFrame(compositionType);
 }
+#endif
 
 void DisplayDevice::swapBuffers(HWComposer& hwc) const {
+#ifdef USE_HWC2
+    if (hwc.hasClientComposition(mHwcDisplayId)) {
+#else
     // We need to call eglSwapBuffers() if:
     //  (1) we don't have a hardware composer, or
     //  (2) we did GLES composition this frame, and either
@@ -244,6 +305,7 @@
     if (hwc.initCheck() != NO_ERROR ||
             (hwc.hasGlesComposition(mHwcDisplayId) &&
              (hwc.supportsFramebufferTarget() || mType >= DISPLAY_VIRTUAL))) {
+#endif
         EGLBoolean success = eglSwapBuffers(mDisplay, mSurface);
         if (!success) {
             EGLint error = eglGetError();
@@ -265,11 +327,17 @@
     }
 }
 
+#ifdef USE_HWC2
+void DisplayDevice::onSwapBuffersCompleted() const {
+    mDisplaySurface->onFrameCommitted();
+}
+#else
 void DisplayDevice::onSwapBuffersCompleted(HWComposer& hwc) const {
     if (hwc.initCheck() == NO_ERROR) {
         mDisplaySurface->onFrameCommitted();
     }
 }
+#endif
 
 uint32_t DisplayDevice::getFlags() const
 {
@@ -298,28 +366,20 @@
         false, Transform::ROT_0);
 }
 
+const sp<Fence>& DisplayDevice::getClientTargetAcquireFence() const {
+    return mDisplaySurface->getClientTargetAcquireFence();
+}
+
 // ----------------------------------------------------------------------------
 
 void DisplayDevice::setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers) {
     mVisibleLayersSortedByZ = layers;
-    mSecureLayerVisible = false;
-    size_t count = layers.size();
-    for (size_t i=0 ; i<count ; i++) {
-        const sp<Layer>& layer(layers[i]);
-        if (layer->isSecure()) {
-            mSecureLayerVisible = true;
-        }
-    }
 }
 
 const Vector< sp<Layer> >& DisplayDevice::getVisibleLayersSortedByZ() const {
     return mVisibleLayersSortedByZ;
 }
 
-bool DisplayDevice::getSecureLayerVisible() const {
-    return mSecureLayerVisible;
-}
-
 Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
     Region dirty;
     if (repaintEverything) {
@@ -492,22 +552,44 @@
     }
 
     mOrientation = orientation;
+    if (mType == DisplayType::DISPLAY_PRIMARY) {
+        uint32_t transform = 0;
+        switch (mOrientation) {
+            case DisplayState::eOrientationDefault:
+                transform = Transform::ROT_0;
+                break;
+            case DisplayState::eOrientation90:
+                transform = Transform::ROT_90;
+                break;
+            case DisplayState::eOrientation180:
+                transform = Transform::ROT_180;
+                break;
+            case DisplayState::eOrientation270:
+                transform = Transform::ROT_270;
+                break;
+        }
+        sPrimaryDisplayOrientation = transform;
+    }
     mViewport = viewport;
     mFrame = frame;
 }
 
+uint32_t DisplayDevice::getPrimaryDisplayOrientationTransform() {
+    return sPrimaryDisplayOrientation;
+}
+
 void DisplayDevice::dump(String8& result) const {
     const Transform& tr(mGlobalTransform);
     result.appendFormat(
         "+ DisplayDevice: %s\n"
         "   type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
-        "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
+        "flips=%u, isSecure=%d, powerMode=%d, activeConfig=%d, numLayers=%zu\n"
         "   v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
         "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
         mDisplayName.string(), mType, mHwcDisplayId,
         mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
         mOrientation, tr.getType(), getPageFlipCount(),
-        mIsSecure, mSecureLayerVisible, mPowerMode, mActiveConfig,
+        mIsSecure, mPowerMode, mActiveConfig,
         mVisibleLayersSortedByZ.size(),
         mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
         mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 8695a44..dd9b104 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -17,21 +17,31 @@
 #ifndef ANDROID_DISPLAY_DEVICE_H
 #define ANDROID_DISPLAY_DEVICE_H
 
+#include "Transform.h"
+
 #include <stdlib.h>
 
+#ifndef USE_HWC2
 #include <ui/PixelFormat.h>
+#endif
 #include <ui/Region.h>
 
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#ifdef USE_HWC2
+#include <binder/IBinder.h>
+#include <utils/RefBase.h>
+#endif
 #include <utils/Mutex.h>
 #include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include <hardware/hwcomposer_defs.h>
 
-#include "Transform.h"
+#ifdef USE_HWC2
+#include <memory>
+#endif
 
 struct ANativeWindow;
 
@@ -39,6 +49,7 @@
 
 struct DisplayInfo;
 class DisplaySurface;
+class Fence;
 class IGraphicBufferProducer;
 class Layer;
 class SurfaceFlinger;
@@ -75,8 +86,10 @@
     DisplayDevice(
             const sp<SurfaceFlinger>& flinger,
             DisplayType type,
-            int32_t hwcId,  // negative for non-HWC-composited displays
+            int32_t hwcId,
+#ifndef USE_HWC2
             int format,
+#endif
             bool isSecure,
             const wp<IBinder>& displayToken,
             const sp<DisplaySurface>& displaySurface,
@@ -99,14 +112,15 @@
 
     int         getWidth() const;
     int         getHeight() const;
+#ifndef USE_HWC2
     PixelFormat getFormat() const;
+#endif
     uint32_t    getFlags() const;
 
     EGLSurface  getEGLSurface() const;
 
     void                    setVisibleLayersSortedByZ(const Vector< sp<Layer> >& layers);
     const Vector< sp<Layer> >& getVisibleLayersSortedByZ() const;
-    bool                    getSecureLayerVisible() const;
     Region                  getDirtyRegion(bool repaintEverything) const;
 
     void                    setLayerStack(uint32_t stack);
@@ -115,6 +129,7 @@
 
     int                     getOrientation() const { return mOrientation; }
     uint32_t                getOrientationTransform() const;
+    static uint32_t         getPrimaryDisplayOrientationTransform();
     const Transform&        getTransform() const { return mGlobalTransform; }
     const Rect              getViewport() const { return mViewport; }
     const Rect              getFrame() const { return mFrame; }
@@ -129,13 +144,23 @@
     // We pass in mustRecompose so we can keep VirtualDisplaySurface's state
     // machine happy without actually queueing a buffer if nothing has changed
     status_t beginFrame(bool mustRecompose) const;
+#ifdef USE_HWC2
+    status_t prepareFrame(HWComposer& hwc);
+#else
     status_t prepareFrame(const HWComposer& hwc) const;
+#endif
 
     void swapBuffers(HWComposer& hwc) const;
+#ifndef USE_HWC2
     status_t compositionComplete() const;
+#endif
 
     // called after h/w composer has completed its set() call
+#ifdef USE_HWC2
+    void onSwapBuffersCompleted() const;
+#else
     void onSwapBuffersCompleted(HWComposer& hwc) const;
+#endif
 
     Rect getBounds() const {
         return Rect(mDisplayWidth, mDisplayHeight);
@@ -148,6 +173,8 @@
     EGLBoolean makeCurrent(EGLDisplay dpy, EGLContext ctx) const;
     void setViewportAndProjection() const;
 
+    const sp<Fence>& getClientTargetAcquireFence() const;
+
     /* ------------------------------------------------------------------------
      * Display power mode management.
      */
@@ -188,7 +215,9 @@
     EGLSurface      mSurface;
     int             mDisplayWidth;
     int             mDisplayHeight;
+#ifndef USE_HWC2
     PixelFormat     mFormat;
+#endif
     uint32_t        mFlags;
     mutable uint32_t mPageFlipCount;
     String8         mDisplayName;
@@ -202,10 +231,6 @@
     // list of visible layers on that display
     Vector< sp<Layer> > mVisibleLayersSortedByZ;
 
-    // Whether we have a visible secure layer on this display
-    bool mSecureLayerVisible;
-
-
     /*
      * Transaction state
      */
@@ -214,6 +239,7 @@
 
     uint32_t mLayerStack;
     int mOrientation;
+    static uint32_t sPrimaryDisplayOrientation;
     // user-provided visible area of the layer stack
     Rect mViewport;
     // user-provided rectangle where mViewport gets mapped to
diff --git a/services/surfaceflinger/DisplayHardware/DisplaySurface.h b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
index 2f743c1..d801bb3 100644
--- a/services/surfaceflinger/DisplayHardware/DisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/DisplaySurface.h
@@ -49,11 +49,13 @@
     };
     virtual status_t prepareFrame(CompositionType compositionType) = 0;
 
+#ifndef USE_HWC2
     // Should be called when composition rendering is complete for a frame (but
     // eglSwapBuffers hasn't necessarily been called). Required by certain
     // older drivers for synchronization.
     // TODO: Remove this when we drop support for HWC 1.0.
     virtual status_t compositionComplete() = 0;
+#endif
 
     // Inform the surface that GLES composition is complete for this frame, and
     // the surface should make sure that HWComposer has the correct buffer for
@@ -74,6 +76,8 @@
 
     virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
 
+    virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
+
 protected:
     DisplaySurface() {}
     virtual ~DisplaySurface() {}
diff --git a/services/surfaceflinger/DisplayHardware/FloatRect.h b/services/surfaceflinger/DisplayHardware/FloatRect.h
index b08a951..9ad1040 100644
--- a/services/surfaceflinger/DisplayHardware/FloatRect.h
+++ b/services/surfaceflinger/DisplayHardware/FloatRect.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SF_FLOAT_RECT
 #define ANDROID_SF_FLOAT_RECT
 
+#include <ui/Rect.h>
 #include <utils/TypeHelpers.h>
 
 namespace android {
@@ -29,7 +30,8 @@
     float right;
     float bottom;
 
-    inline FloatRect() { }
+    inline FloatRect()
+        : left(0), top(0), right(0), bottom(0) { }
     inline FloatRect(const Rect& other)
         : left(other.left), top(other.top), right(other.right), bottom(other.bottom) { }
 
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 6ef3295..7368d77 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -15,6 +15,10 @@
  ** limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "FramebufferSurface"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -56,17 +60,35 @@
     ConsumerBase(consumer),
     mDisplayType(disp),
     mCurrentBufferSlot(-1),
-    mCurrentBuffer(0),
+    mCurrentBuffer(),
+    mCurrentFence(Fence::NO_FENCE),
+#ifdef USE_HWC2
+    mHwc(hwc),
+    mHasPendingRelease(false),
+    mPreviousBufferSlot(BufferQueue::INVALID_BUFFER_SLOT),
+    mPreviousBuffer()
+#else
     mHwc(hwc)
+#endif
 {
+#ifdef USE_HWC2
+    ALOGV("Creating for display %d", disp);
+#endif
+
     mName = "FramebufferSurface";
     mConsumer->setConsumerName(mName);
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
                                        GRALLOC_USAGE_HW_RENDER |
                                        GRALLOC_USAGE_HW_COMPOSER);
+#ifdef USE_HWC2
+    const auto& activeConfig = mHwc.getActiveConfig(disp);
+    mConsumer->setDefaultBufferSize(activeConfig->getWidth(),
+            activeConfig->getHeight());
+#else
     mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
-    mConsumer->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));
-    mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
+    mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
+#endif
+    mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
 }
 
 status_t FramebufferSurface::beginFrame(bool /*mustRecompose*/) {
@@ -78,13 +100,35 @@
 }
 
 status_t FramebufferSurface::advanceFrame() {
+#ifdef USE_HWC2
+    sp<GraphicBuffer> buf;
+    sp<Fence> acquireFence(Fence::NO_FENCE);
+    android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+    status_t result = nextBuffer(buf, acquireFence, dataspace);
+    if (result != NO_ERROR) {
+        ALOGE("error latching next FramebufferSurface buffer: %s (%d)",
+                strerror(-result), result);
+        return result;
+    }
+    result = mHwc.setClientTarget(mDisplayType, acquireFence, buf, dataspace);
+    if (result != NO_ERROR) {
+        ALOGE("error posting framebuffer: %d", result);
+    }
+    return result;
+#else
     // Once we remove FB HAL support, we can call nextBuffer() from here
     // instead of using onFrameAvailable(). No real benefit, except it'll be
     // more like VirtualDisplaySurface.
     return NO_ERROR;
+#endif
 }
 
+#ifdef USE_HWC2
+status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer,
+        sp<Fence>& outFence, android_dataspace_t& outDataspace) {
+#else
 status_t FramebufferSurface::nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence) {
+#endif
     Mutex::Autolock lock(mMutex);
 
     BufferItem item;
@@ -106,7 +150,12 @@
     // releaseBuffer call and we should be in the same state we'd be in if we
     // had released the old buffer first.
     if (mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT &&
-        item.mBuf != mCurrentBufferSlot) {
+        item.mSlot != mCurrentBufferSlot) {
+#ifdef USE_HWC2
+        mHasPendingRelease = true;
+        mPreviousBufferSlot = mCurrentBufferSlot;
+        mPreviousBuffer = mCurrentBuffer;
+#else
         // Release the previous buffer.
         err = releaseBufferLocked(mCurrentBufferSlot, mCurrentBuffer,
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
@@ -114,14 +163,21 @@
             ALOGE("error releasing buffer: %s (%d)", strerror(-err), err);
             return err;
         }
+#endif
     }
-    mCurrentBufferSlot = item.mBuf;
+    mCurrentBufferSlot = item.mSlot;
     mCurrentBuffer = mSlots[mCurrentBufferSlot].mGraphicBuffer;
+    mCurrentFence = item.mFence;
+
     outFence = item.mFence;
     outBuffer = mCurrentBuffer;
+#ifdef USE_HWC2
+    outDataspace = item.mDataSpace;
+#endif
     return NO_ERROR;
 }
 
+#ifndef USE_HWC2
 // Overrides ConsumerBase::onFrameAvailable(), does not call base class impl.
 void FramebufferSurface::onFrameAvailable(const BufferItem& /* item */) {
     sp<GraphicBuffer> buf;
@@ -137,6 +193,7 @@
         ALOGE("error posting framebuffer: %d", err);
     }
 }
+#endif
 
 void FramebufferSurface::freeBufferLocked(int slotIndex) {
     ConsumerBase::freeBufferLocked(slotIndex);
@@ -146,6 +203,24 @@
 }
 
 void FramebufferSurface::onFrameCommitted() {
+#ifdef USE_HWC2
+    if (mHasPendingRelease) {
+        sp<Fence> fence = mHwc.getRetireFence(mDisplayType);
+        if (fence->isValid()) {
+            status_t result = addReleaseFence(mPreviousBufferSlot,
+                    mPreviousBuffer, fence);
+            ALOGE_IF(result != NO_ERROR, "onFrameCommitted: failed to add the"
+                    " fence: %s (%d)", strerror(-result), result);
+        }
+        status_t result = releaseBufferLocked(mPreviousBufferSlot,
+                mPreviousBuffer, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
+        ALOGE_IF(result != NO_ERROR, "onFrameCommitted: error releasing buffer:"
+                " %s (%d)", strerror(-result), result);
+
+        mPreviousBuffer.clear();
+        mHasPendingRelease = false;
+    }
+#else
     sp<Fence> fence = mHwc.getAndResetReleaseFence(mDisplayType);
     if (fence->isValid() &&
             mCurrentBufferSlot != BufferQueue::INVALID_BUFFER_SLOT) {
@@ -154,12 +229,15 @@
         ALOGE_IF(err, "setReleaseFenceFd: failed to add the fence: %s (%d)",
                 strerror(-err), err);
     }
+#endif
 }
 
+#ifndef USE_HWC2
 status_t FramebufferSurface::compositionComplete()
 {
     return mHwc.fbCompositionComplete();
 }
+#endif
 
 void FramebufferSurface::dumpAsString(String8& result) const {
     ConsumerBase::dump(result);
@@ -167,10 +245,16 @@
 
 void FramebufferSurface::dumpLocked(String8& result, const char* prefix) const
 {
+#ifndef USE_HWC2
     mHwc.fbDump(result);
+#endif
     ConsumerBase::dumpLocked(result, prefix);
 }
 
+const sp<Fence>& FramebufferSurface::getClientTargetAcquireFence() const {
+    return mCurrentFence;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 3d17840..439435a 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,7 +41,9 @@
 
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
+#ifndef USE_HWC2
     virtual status_t compositionComplete();
+#endif
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
@@ -50,10 +52,14 @@
     // displays.
     virtual void resizeBuffers(const uint32_t /*w*/, const uint32_t /*h*/) { };
 
+    virtual const sp<Fence>& getClientTargetAcquireFence() const override;
+
 private:
     virtual ~FramebufferSurface() { }; // this class cannot be overloaded
 
+#ifndef USE_HWC2
     virtual void onFrameAvailable(const BufferItem& item);
+#endif
     virtual void freeBufferLocked(int slotIndex);
 
     virtual void dumpLocked(String8& result, const char* prefix) const;
@@ -61,7 +67,12 @@
     // nextBuffer waits for and then latches the next buffer from the
     // BufferQueue and releases the previously latched buffer to the
     // BufferQueue.  The new buffer is returned in the 'buffer' argument.
+#ifdef USE_HWC2
+    status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,
+            android_dataspace_t& outDataspace);
+#else
     status_t nextBuffer(sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence);
+#endif
 
     // mDisplayType must match one of the HWC display types
     int mDisplayType;
@@ -75,8 +86,18 @@
     // no current buffer.
     sp<GraphicBuffer> mCurrentBuffer;
 
+    // mCurrentFence is the current buffer's acquire fence
+    sp<Fence> mCurrentFence;
+
     // Hardware composer, owned by SurfaceFlinger.
     HWComposer& mHwc;
+
+#ifdef USE_HWC2
+    // Previous buffer to release after getting an updated retire fence
+    bool mHasPendingRelease;
+    int mPreviousBufferSlot;
+    sp<GraphicBuffer> mPreviousBuffer;
+#endif
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
new file mode 100644
index 0000000..f898ada
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -0,0 +1,1094 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// #define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWC2"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "HWC2.h"
+
+#include "FloatRect.h"
+
+#include <ui/Fence.h>
+#include <ui/GraphicBuffer.h>
+#include <ui/Region.h>
+
+#include <android/configuration.h>
+
+#include <algorithm>
+#include <inttypes.h>
+
+extern "C" {
+    static void hotplug_hook(hwc2_callback_data_t callbackData,
+            hwc2_display_t displayId, int32_t intConnected) {
+        auto device = static_cast<HWC2::Device*>(callbackData);
+        auto display = device->getDisplayById(displayId);
+        if (display) {
+            auto connected = static_cast<HWC2::Connection>(intConnected);
+            device->callHotplug(std::move(display), connected);
+        } else {
+            ALOGE("Hotplug callback called with unknown display %" PRIu64,
+                    displayId);
+        }
+    }
+
+    static void refresh_hook(hwc2_callback_data_t callbackData,
+            hwc2_display_t displayId) {
+        auto device = static_cast<HWC2::Device*>(callbackData);
+        auto display = device->getDisplayById(displayId);
+        if (display) {
+            device->callRefresh(std::move(display));
+        } else {
+            ALOGE("Refresh callback called with unknown display %" PRIu64,
+                    displayId);
+        }
+    }
+
+    static void vsync_hook(hwc2_callback_data_t callbackData,
+            hwc2_display_t displayId, int64_t timestamp) {
+        auto device = static_cast<HWC2::Device*>(callbackData);
+        auto display = device->getDisplayById(displayId);
+        if (display) {
+            device->callVsync(std::move(display), timestamp);
+        } else {
+            ALOGE("Vsync callback called with unknown display %" PRIu64,
+                    displayId);
+        }
+    }
+}
+
+using android::Fence;
+using android::FloatRect;
+using android::GraphicBuffer;
+using android::HdrCapabilities;
+using android::Rect;
+using android::Region;
+using android::sp;
+
+namespace HWC2 {
+
+// Device methods
+
+Device::Device(hwc2_device_t* device)
+  : mHwcDevice(device),
+    mCreateVirtualDisplay(nullptr),
+    mDestroyVirtualDisplay(nullptr),
+    mDump(nullptr),
+    mGetMaxVirtualDisplayCount(nullptr),
+    mRegisterCallback(nullptr),
+    mAcceptDisplayChanges(nullptr),
+    mCreateLayer(nullptr),
+    mDestroyLayer(nullptr),
+    mGetActiveConfig(nullptr),
+    mGetChangedCompositionTypes(nullptr),
+    mGetColorModes(nullptr),
+    mGetDisplayAttribute(nullptr),
+    mGetDisplayConfigs(nullptr),
+    mGetDisplayName(nullptr),
+    mGetDisplayRequests(nullptr),
+    mGetDisplayType(nullptr),
+    mGetDozeSupport(nullptr),
+    mGetHdrCapabilities(nullptr),
+    mGetReleaseFences(nullptr),
+    mPresentDisplay(nullptr),
+    mSetActiveConfig(nullptr),
+    mSetClientTarget(nullptr),
+    mSetColorMode(nullptr),
+    mSetColorTransform(nullptr),
+    mSetOutputBuffer(nullptr),
+    mSetPowerMode(nullptr),
+    mSetVsyncEnabled(nullptr),
+    mValidateDisplay(nullptr),
+    mSetCursorPosition(nullptr),
+    mSetLayerBuffer(nullptr),
+    mSetLayerSurfaceDamage(nullptr),
+    mSetLayerBlendMode(nullptr),
+    mSetLayerColor(nullptr),
+    mSetLayerCompositionType(nullptr),
+    mSetLayerDataspace(nullptr),
+    mSetLayerDisplayFrame(nullptr),
+    mSetLayerPlaneAlpha(nullptr),
+    mSetLayerSidebandStream(nullptr),
+    mSetLayerSourceCrop(nullptr),
+    mSetLayerTransform(nullptr),
+    mSetLayerVisibleRegion(nullptr),
+    mSetLayerZOrder(nullptr),
+    mCapabilities(),
+    mDisplays(),
+    mHotplug(),
+    mPendingHotplugs(),
+    mRefresh(),
+    mPendingRefreshes(),
+    mVsync(),
+    mPendingVsyncs()
+{
+    loadCapabilities();
+    loadFunctionPointers();
+    registerCallbacks();
+}
+
+Device::~Device()
+{
+    if (mHwcDevice == nullptr) {
+        return;
+    }
+
+    for (auto element : mDisplays) {
+        auto display = element.second;
+
+        DisplayType displayType = HWC2::DisplayType::Invalid;
+        auto error = display->getType(&displayType);
+        if (error != Error::None) {
+            ALOGE("~Device: Failed to determine type of display %" PRIu64
+                    ": %s (%d)", display->getId(), to_string(error).c_str(),
+                    static_cast<int32_t>(error));
+            continue;
+        }
+
+        if (displayType == HWC2::DisplayType::Physical) {
+            error = display->setVsyncEnabled(HWC2::Vsync::Disable);
+            if (error != Error::None) {
+                ALOGE("~Device: Failed to disable vsync for display %" PRIu64
+                        ": %s (%d)", display->getId(), to_string(error).c_str(),
+                        static_cast<int32_t>(error));
+            }
+        }
+    }
+
+    hwc2_close(mHwcDevice);
+}
+
+// Required by HWC2 device
+
+std::string Device::dump() const
+{
+    uint32_t numBytes = 0;
+    mDump(mHwcDevice, &numBytes, nullptr);
+
+    std::vector<char> buffer(numBytes);
+    mDump(mHwcDevice, &numBytes, buffer.data());
+
+    return std::string(buffer.data(), buffer.size());
+}
+
+uint32_t Device::getMaxVirtualDisplayCount() const
+{
+    return mGetMaxVirtualDisplayCount(mHwcDevice);
+}
+
+Error Device::createVirtualDisplay(uint32_t width, uint32_t height,
+        std::shared_ptr<Display>* outDisplay)
+{
+    ALOGI("Creating virtual display");
+
+    hwc2_display_t displayId = 0;
+    int32_t intError = mCreateVirtualDisplay(mHwcDevice, width, height,
+            &displayId);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    ALOGI("Created virtual display");
+    *outDisplay = getDisplayById(displayId);
+    (*outDisplay)->setVirtual();
+    return Error::None;
+}
+
+void Device::registerHotplugCallback(HotplugCallback hotplug)
+{
+    ALOGV("registerHotplugCallback");
+    mHotplug = hotplug;
+    for (auto& pending : mPendingHotplugs) {
+        auto& display = pending.first;
+        auto connected = pending.second;
+        ALOGV("Sending pending hotplug(%" PRIu64 ", %s)", display->getId(),
+                to_string(connected).c_str());
+        mHotplug(std::move(display), connected);
+    }
+}
+
+void Device::registerRefreshCallback(RefreshCallback refresh)
+{
+    mRefresh = refresh;
+    for (auto& pending : mPendingRefreshes) {
+        mRefresh(std::move(pending));
+    }
+}
+
+void Device::registerVsyncCallback(VsyncCallback vsync)
+{
+    mVsync = vsync;
+    for (auto& pending : mPendingVsyncs) {
+        auto& display = pending.first;
+        auto timestamp = pending.second;
+        mVsync(std::move(display), timestamp);
+    }
+}
+
+// For use by Device callbacks
+
+void Device::callHotplug(std::shared_ptr<Display> display, Connection connected)
+{
+    if (connected == Connection::Connected) {
+        if (!display->isConnected()) {
+            display->loadConfigs();
+            display->setConnected(true);
+        }
+    } else {
+        display->setConnected(false);
+        mDisplays.erase(display->getId());
+    }
+
+    if (mHotplug) {
+        mHotplug(std::move(display), connected);
+    } else {
+        ALOGV("callHotplug called, but no valid callback registered, storing");
+        mPendingHotplugs.emplace_back(std::move(display), connected);
+    }
+}
+
+void Device::callRefresh(std::shared_ptr<Display> display)
+{
+    if (mRefresh) {
+        mRefresh(std::move(display));
+    } else {
+        ALOGV("callRefresh called, but no valid callback registered, storing");
+        mPendingRefreshes.emplace_back(std::move(display));
+    }
+}
+
+void Device::callVsync(std::shared_ptr<Display> display, nsecs_t timestamp)
+{
+    if (mVsync) {
+        mVsync(std::move(display), timestamp);
+    } else {
+        ALOGV("callVsync called, but no valid callback registered, storing");
+        mPendingVsyncs.emplace_back(std::move(display), timestamp);
+    }
+}
+
+// Other Device methods
+
+std::shared_ptr<Display> Device::getDisplayById(hwc2_display_t id) {
+    if (mDisplays.count(id) != 0) {
+        return mDisplays.at(id);
+    }
+
+    auto display = std::make_shared<Display>(*this, id);
+    mDisplays.emplace(id, display);
+    return display;
+}
+
+// Device initialization methods
+
+void Device::loadCapabilities()
+{
+    static_assert(sizeof(Capability) == sizeof(int32_t),
+            "Capability size has changed");
+    uint32_t numCapabilities = 0;
+    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, nullptr);
+    mCapabilities.resize(numCapabilities);
+    auto asInt = reinterpret_cast<int32_t*>(mCapabilities.data());
+    mHwcDevice->getCapabilities(mHwcDevice, &numCapabilities, asInt);
+}
+
+bool Device::hasCapability(HWC2::Capability capability) const
+{
+    return std::find(mCapabilities.cbegin(), mCapabilities.cend(),
+            capability) != mCapabilities.cend();
+}
+
+void Device::loadFunctionPointers()
+{
+    // For all of these early returns, we log an error message inside
+    // loadFunctionPointer specifying which function failed to load
+
+    // Display function pointers
+    if (!loadFunctionPointer(FunctionDescriptor::CreateVirtualDisplay,
+            mCreateVirtualDisplay)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::DestroyVirtualDisplay,
+            mDestroyVirtualDisplay)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::Dump, mDump)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetMaxVirtualDisplayCount,
+            mGetMaxVirtualDisplayCount)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::RegisterCallback,
+            mRegisterCallback)) return;
+
+    // Device function pointers
+    if (!loadFunctionPointer(FunctionDescriptor::AcceptDisplayChanges,
+            mAcceptDisplayChanges)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::CreateLayer,
+            mCreateLayer)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::DestroyLayer,
+            mDestroyLayer)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetActiveConfig,
+            mGetActiveConfig)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetChangedCompositionTypes,
+            mGetChangedCompositionTypes)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetColorModes,
+            mGetColorModes)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayAttribute,
+            mGetDisplayAttribute)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayConfigs,
+            mGetDisplayConfigs)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayName,
+            mGetDisplayName)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayRequests,
+            mGetDisplayRequests)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetDisplayType,
+            mGetDisplayType)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetDozeSupport,
+            mGetDozeSupport)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetHdrCapabilities,
+            mGetHdrCapabilities)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::GetReleaseFences,
+            mGetReleaseFences)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::PresentDisplay,
+            mPresentDisplay)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetActiveConfig,
+            mSetActiveConfig)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetClientTarget,
+            mSetClientTarget)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetColorMode,
+            mSetColorMode)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetColorTransform,
+            mSetColorTransform)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetOutputBuffer,
+            mSetOutputBuffer)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetPowerMode,
+            mSetPowerMode)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetVsyncEnabled,
+            mSetVsyncEnabled)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::ValidateDisplay,
+            mValidateDisplay)) return;
+
+    // Layer function pointers
+    if (!loadFunctionPointer(FunctionDescriptor::SetCursorPosition,
+            mSetCursorPosition)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerBuffer,
+            mSetLayerBuffer)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerSurfaceDamage,
+            mSetLayerSurfaceDamage)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerBlendMode,
+            mSetLayerBlendMode)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerColor,
+            mSetLayerColor)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerCompositionType,
+            mSetLayerCompositionType)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerDataspace,
+            mSetLayerDataspace)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerDisplayFrame,
+            mSetLayerDisplayFrame)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerPlaneAlpha,
+            mSetLayerPlaneAlpha)) return;
+    if (hasCapability(Capability::SidebandStream)) {
+        if (!loadFunctionPointer(FunctionDescriptor::SetLayerSidebandStream,
+                mSetLayerSidebandStream)) return;
+    }
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerSourceCrop,
+            mSetLayerSourceCrop)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerTransform,
+            mSetLayerTransform)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerVisibleRegion,
+            mSetLayerVisibleRegion)) return;
+    if (!loadFunctionPointer(FunctionDescriptor::SetLayerZOrder,
+            mSetLayerZOrder)) return;
+}
+
+void Device::registerCallbacks()
+{
+    registerCallback<HWC2_PFN_HOTPLUG>(Callback::Hotplug, hotplug_hook);
+    registerCallback<HWC2_PFN_REFRESH>(Callback::Refresh, refresh_hook);
+    registerCallback<HWC2_PFN_VSYNC>(Callback::Vsync, vsync_hook);
+}
+
+
+// For use by Display
+
+void Device::destroyVirtualDisplay(hwc2_display_t display)
+{
+    ALOGI("Destroying virtual display");
+    int32_t intError = mDestroyVirtualDisplay(mHwcDevice, display);
+    auto error = static_cast<Error>(intError);
+    ALOGE_IF(error != Error::None, "destroyVirtualDisplay(%" PRIu64 ") failed:"
+            " %s (%d)", display, to_string(error).c_str(), intError);
+}
+
+// Display methods
+
+Display::Display(Device& device, hwc2_display_t id)
+  : mDevice(device),
+    mId(id),
+    mIsConnected(false),
+    mIsVirtual(false)
+{
+    ALOGV("Created display %" PRIu64, id);
+}
+
+Display::~Display()
+{
+    ALOGV("Destroyed display %" PRIu64, mId);
+    if (mIsVirtual) {
+        mDevice.destroyVirtualDisplay(mId);
+    }
+}
+
+Display::Config::Config(Display& display, hwc2_config_t id)
+  : mDisplay(display),
+    mId(id),
+    mWidth(-1),
+    mHeight(-1),
+    mVsyncPeriod(-1),
+    mDpiX(-1),
+    mDpiY(-1) {}
+
+Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
+  : mConfig(new Config(display, id)) {}
+
+float Display::Config::Builder::getDefaultDensity() {
+    // Default density is based on TVs: 1080p displays get XHIGH density, lower-
+    // resolution displays get TV density. Maybe eventually we'll need to update
+    // it for 4k displays, though hopefully those will just report accurate DPI
+    // information to begin with. This is also used for virtual displays and
+    // older HWC implementations, so be careful about orientation.
+
+    auto longDimension = std::max(mConfig->mWidth, mConfig->mHeight);
+    if (longDimension >= 1080) {
+        return ACONFIGURATION_DENSITY_XHIGH;
+    } else {
+        return ACONFIGURATION_DENSITY_TV;
+    }
+}
+
+// Required by HWC2 display
+
+Error Display::acceptChanges()
+{
+    int32_t intError = mDevice.mAcceptDisplayChanges(mDevice.mHwcDevice, mId);
+    return static_cast<Error>(intError);
+}
+
+Error Display::createLayer(std::shared_ptr<Layer>* outLayer)
+{
+    hwc2_layer_t layerId = 0;
+    int32_t intError = mDevice.mCreateLayer(mDevice.mHwcDevice, mId, &layerId);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    auto layer = std::make_shared<Layer>(shared_from_this(), layerId);
+    mLayers.emplace(layerId, layer);
+    *outLayer = std::move(layer);
+    return Error::None;
+}
+
+Error Display::getActiveConfig(
+        std::shared_ptr<const Display::Config>* outConfig) const
+{
+    ALOGV("[%" PRIu64 "] getActiveConfig", mId);
+    hwc2_config_t configId = 0;
+    int32_t intError = mDevice.mGetActiveConfig(mDevice.mHwcDevice, mId,
+            &configId);
+    auto error = static_cast<Error>(intError);
+
+    if (error != Error::None) {
+        return error;
+    }
+
+    if (mConfigs.count(configId) != 0) {
+        *outConfig = mConfigs.at(configId);
+    } else {
+        ALOGE("[%" PRIu64 "] getActiveConfig returned unknown config %u", mId,
+                configId);
+        // Return no error, but the caller needs to check for a null pointer to
+        // detect this case
+        *outConfig = nullptr;
+    }
+
+    return Error::None;
+}
+
+Error Display::getChangedCompositionTypes(
+        std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes)
+{
+    uint32_t numElements = 0;
+    int32_t intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice,
+            mId, &numElements, nullptr, nullptr);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::vector<hwc2_layer_t> layerIds(numElements);
+    std::vector<int32_t> types(numElements);
+    intError = mDevice.mGetChangedCompositionTypes(mDevice.mHwcDevice, mId,
+            &numElements, layerIds.data(), types.data());
+    error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    outTypes->clear();
+    outTypes->reserve(numElements);
+    for (uint32_t element = 0; element < numElements; ++element) {
+        auto layer = getLayerById(layerIds[element]);
+        if (layer) {
+            auto type = static_cast<Composition>(types[element]);
+            ALOGV("getChangedCompositionTypes: adding %" PRIu64 " %s",
+                    layer->getId(), to_string(type).c_str());
+            outTypes->emplace(layer, type);
+        } else {
+            ALOGE("getChangedCompositionTypes: invalid layer %" PRIu64 " found"
+                    " on display %" PRIu64, layerIds[element], mId);
+        }
+    }
+
+    return Error::None;
+}
+
+Error Display::getColorModes(std::vector<int32_t>* outModes) const
+{
+    uint32_t numModes = 0;
+    int32_t intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId,
+            &numModes, nullptr);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None)  {
+        return error;
+    }
+
+    std::vector<int32_t> modes(numModes);
+    intError = mDevice.mGetColorModes(mDevice.mHwcDevice, mId, &numModes,
+            modes.data());
+    error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::swap(*outModes, modes);
+    return Error::None;
+}
+
+std::vector<std::shared_ptr<const Display::Config>> Display::getConfigs() const
+{
+    std::vector<std::shared_ptr<const Config>> configs;
+    for (const auto& element : mConfigs) {
+        configs.emplace_back(element.second);
+    }
+    return configs;
+}
+
+Error Display::getName(std::string* outName) const
+{
+    uint32_t size;
+    int32_t intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
+            nullptr);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::vector<char> rawName(size);
+    intError = mDevice.mGetDisplayName(mDevice.mHwcDevice, mId, &size,
+            rawName.data());
+    error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    *outName = std::string(rawName.cbegin(), rawName.cend());
+    return Error::None;
+}
+
+Error Display::getRequests(HWC2::DisplayRequest* outDisplayRequests,
+        std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
+                outLayerRequests)
+{
+    int32_t intDisplayRequests = 0;
+    uint32_t numElements = 0;
+    int32_t intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
+            &intDisplayRequests, &numElements, nullptr, nullptr);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::vector<hwc2_layer_t> layerIds(numElements);
+    std::vector<int32_t> layerRequests(numElements);
+    intError = mDevice.mGetDisplayRequests(mDevice.mHwcDevice, mId,
+            &intDisplayRequests, &numElements, layerIds.data(),
+            layerRequests.data());
+    error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    *outDisplayRequests = static_cast<DisplayRequest>(intDisplayRequests);
+    outLayerRequests->clear();
+    outLayerRequests->reserve(numElements);
+    for (uint32_t element = 0; element < numElements; ++element) {
+        auto layer = getLayerById(layerIds[element]);
+        if (layer) {
+            auto layerRequest =
+                    static_cast<LayerRequest>(layerRequests[element]);
+            outLayerRequests->emplace(layer, layerRequest);
+        } else {
+            ALOGE("getRequests: invalid layer %" PRIu64 " found on display %"
+                    PRIu64, layerIds[element], mId);
+        }
+    }
+
+    return Error::None;
+}
+
+Error Display::getType(DisplayType* outType) const
+{
+    int32_t intType = 0;
+    int32_t intError = mDevice.mGetDisplayType(mDevice.mHwcDevice, mId,
+            &intType);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    *outType = static_cast<DisplayType>(intType);
+    return Error::None;
+}
+
+Error Display::supportsDoze(bool* outSupport) const
+{
+    int32_t intSupport = 0;
+    int32_t intError = mDevice.mGetDozeSupport(mDevice.mHwcDevice, mId,
+            &intSupport);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+    *outSupport = static_cast<bool>(intSupport);
+    return Error::None;
+}
+
+Error Display::getHdrCapabilities(
+        std::unique_ptr<HdrCapabilities>* outCapabilities) const
+{
+    uint32_t numTypes = 0;
+    float maxLuminance = -1.0f;
+    float maxAverageLuminance = -1.0f;
+    float minLuminance = -1.0f;
+    int32_t intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId,
+            &numTypes, nullptr, &maxLuminance, &maxAverageLuminance,
+            &minLuminance);
+    auto error = static_cast<HWC2::Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::vector<int32_t> types(numTypes);
+    intError = mDevice.mGetHdrCapabilities(mDevice.mHwcDevice, mId, &numTypes,
+            types.data(), &maxLuminance, &maxAverageLuminance, &minLuminance);
+    error = static_cast<HWC2::Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    *outCapabilities = std::make_unique<HdrCapabilities>(std::move(types),
+            maxLuminance, maxAverageLuminance, minLuminance);
+    return Error::None;
+}
+
+Error Display::getReleaseFences(
+        std::unordered_map<std::shared_ptr<Layer>, sp<Fence>>* outFences) const
+{
+    uint32_t numElements = 0;
+    int32_t intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId,
+            &numElements, nullptr, nullptr);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::vector<hwc2_layer_t> layerIds(numElements);
+    std::vector<int32_t> fenceFds(numElements);
+    intError = mDevice.mGetReleaseFences(mDevice.mHwcDevice, mId, &numElements,
+            layerIds.data(), fenceFds.data());
+    error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    std::unordered_map<std::shared_ptr<Layer>, sp<Fence>> releaseFences;
+    releaseFences.reserve(numElements);
+    for (uint32_t element = 0; element < numElements; ++element) {
+        auto layer = getLayerById(layerIds[element]);
+        if (layer) {
+            sp<Fence> fence(new Fence(fenceFds[element]));
+            releaseFences.emplace(std::move(layer), fence);
+        } else {
+            ALOGE("getReleaseFences: invalid layer %" PRIu64
+                    " found on display %" PRIu64, layerIds[element], mId);
+            return Error::BadLayer;
+        }
+    }
+
+    *outFences = std::move(releaseFences);
+    return Error::None;
+}
+
+Error Display::present(sp<Fence>* outRetireFence)
+{
+    int32_t retireFenceFd = 0;
+    int32_t intError = mDevice.mPresentDisplay(mDevice.mHwcDevice, mId,
+            &retireFenceFd);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        return error;
+    }
+
+    *outRetireFence = new Fence(retireFenceFd);
+    return Error::None;
+}
+
+Error Display::setActiveConfig(const std::shared_ptr<const Config>& config)
+{
+    if (config->getDisplayId() != mId) {
+        ALOGE("setActiveConfig received config %u for the wrong display %"
+                PRIu64 " (expected %" PRIu64 ")", config->getId(),
+                config->getDisplayId(), mId);
+        return Error::BadConfig;
+    }
+    int32_t intError = mDevice.mSetActiveConfig(mDevice.mHwcDevice, mId,
+            config->getId());
+    return static_cast<Error>(intError);
+}
+
+Error Display::setClientTarget(buffer_handle_t target,
+        const sp<Fence>& acquireFence, android_dataspace_t dataspace)
+{
+    int32_t fenceFd = acquireFence->dup();
+    int32_t intError = mDevice.mSetClientTarget(mDevice.mHwcDevice, mId, target,
+            fenceFd, static_cast<int32_t>(dataspace));
+    return static_cast<Error>(intError);
+}
+
+Error Display::setColorMode(int32_t mode)
+{
+    int32_t intError = mDevice.mSetColorMode(mDevice.mHwcDevice, mId, mode);
+    return static_cast<Error>(intError);
+}
+
+Error Display::setColorTransform(const android::mat4& matrix,
+        android_color_transform_t hint)
+{
+    int32_t intError = mDevice.mSetColorTransform(mDevice.mHwcDevice, mId,
+            matrix.asArray(), static_cast<int32_t>(hint));
+    return static_cast<Error>(intError);
+}
+
+Error Display::setOutputBuffer(const sp<GraphicBuffer>& buffer,
+        const sp<Fence>& releaseFence)
+{
+    int32_t fenceFd = releaseFence->dup();
+    auto handle = buffer->getNativeBuffer()->handle;
+    int32_t intError = mDevice.mSetOutputBuffer(mDevice.mHwcDevice, mId, handle,
+            fenceFd);
+    return static_cast<Error>(intError);
+}
+
+Error Display::setPowerMode(PowerMode mode)
+{
+    auto intMode = static_cast<int32_t>(mode);
+    int32_t intError = mDevice.mSetPowerMode(mDevice.mHwcDevice, mId, intMode);
+    return static_cast<Error>(intError);
+}
+
+Error Display::setVsyncEnabled(Vsync enabled)
+{
+    auto intEnabled = static_cast<int32_t>(enabled);
+    int32_t intError = mDevice.mSetVsyncEnabled(mDevice.mHwcDevice, mId,
+            intEnabled);
+    return static_cast<Error>(intError);
+}
+
+Error Display::validate(uint32_t* outNumTypes, uint32_t* outNumRequests)
+{
+    uint32_t numTypes = 0;
+    uint32_t numRequests = 0;
+    int32_t intError = mDevice.mValidateDisplay(mDevice.mHwcDevice, mId,
+            &numTypes, &numRequests);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None && error != Error::HasChanges) {
+        return error;
+    }
+
+    *outNumTypes = numTypes;
+    *outNumRequests = numRequests;
+    return error;
+}
+
+// For use by Device
+
+int32_t Display::getAttribute(hwc2_config_t configId, Attribute attribute)
+{
+    int32_t value = 0;
+    int32_t intError = mDevice.mGetDisplayAttribute(mDevice.mHwcDevice, mId,
+            configId, static_cast<int32_t>(attribute), &value);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        ALOGE("getDisplayAttribute(%" PRIu64 ", %u, %s) failed: %s (%d)", mId,
+                configId, to_string(attribute).c_str(),
+                to_string(error).c_str(), intError);
+        return -1;
+    }
+    return value;
+}
+
+void Display::loadConfig(hwc2_config_t configId)
+{
+    ALOGV("[%" PRIu64 "] loadConfig(%u)", mId, configId);
+
+    auto config = Config::Builder(*this, configId)
+            .setWidth(getAttribute(configId, Attribute::Width))
+            .setHeight(getAttribute(configId, Attribute::Height))
+            .setVsyncPeriod(getAttribute(configId, Attribute::VsyncPeriod))
+            .setDpiX(getAttribute(configId, Attribute::DpiX))
+            .setDpiY(getAttribute(configId, Attribute::DpiY))
+            .build();
+    mConfigs.emplace(configId, std::move(config));
+}
+
+void Display::loadConfigs()
+{
+    ALOGV("[%" PRIu64 "] loadConfigs", mId);
+
+    uint32_t numConfigs = 0;
+    int32_t intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId,
+            &numConfigs, nullptr);
+    auto error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        ALOGE("[%" PRIu64 "] getDisplayConfigs [1] failed: %s (%d)", mId,
+                to_string(error).c_str(), intError);
+        return;
+    }
+
+    std::vector<hwc2_config_t> configIds(numConfigs);
+    intError = mDevice.mGetDisplayConfigs(mDevice.mHwcDevice, mId, &numConfigs,
+            configIds.data());
+    error = static_cast<Error>(intError);
+    if (error != Error::None) {
+        ALOGE("[%" PRIu64 "] getDisplayConfigs [2] failed: %s (%d)", mId,
+                to_string(error).c_str(), intError);
+        return;
+    }
+
+    for (auto configId : configIds) {
+        loadConfig(configId);
+    }
+}
+
+// For use by Layer
+
+void Display::destroyLayer(hwc2_layer_t layerId)
+{
+    int32_t intError = mDevice.mDestroyLayer(mDevice.mHwcDevice, mId, layerId);
+    auto error = static_cast<Error>(intError);
+    ALOGE_IF(error != Error::None, "destroyLayer(%" PRIu64 ", %" PRIu64 ")"
+            " failed: %s (%d)", mId, layerId, to_string(error).c_str(),
+            intError);
+    mLayers.erase(layerId);
+}
+
+// Other Display methods
+
+std::shared_ptr<Layer> Display::getLayerById(hwc2_layer_t id) const
+{
+    if (mLayers.count(id) == 0) {
+        return nullptr;
+    }
+
+    auto layer = mLayers.at(id).lock();
+    return layer;
+}
+
+// Layer methods
+
+Layer::Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id)
+  : mDisplay(display),
+    mDisplayId(display->getId()),
+    mDevice(display->getDevice()),
+    mId(id)
+{
+    ALOGV("Created layer %" PRIu64 " on display %" PRIu64, id,
+            display->getId());
+}
+
+Layer::~Layer()
+{
+    auto display = mDisplay.lock();
+    if (display) {
+        display->destroyLayer(mId);
+    }
+}
+
+Error Layer::setCursorPosition(int32_t x, int32_t y)
+{
+    int32_t intError = mDevice.mSetCursorPosition(mDevice.mHwcDevice,
+            mDisplayId, mId, x, y);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setBuffer(buffer_handle_t buffer,
+        const sp<Fence>& acquireFence)
+{
+    int32_t fenceFd = acquireFence->dup();
+    int32_t intError = mDevice.mSetLayerBuffer(mDevice.mHwcDevice, mDisplayId,
+            mId, buffer, fenceFd);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setSurfaceDamage(const Region& damage)
+{
+    // We encode default full-screen damage as INVALID_RECT upstream, but as 0
+    // rects for HWC
+    int32_t intError = 0;
+    if (damage.isRect() && damage.getBounds() == Rect::INVALID_RECT) {
+        intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
+                mDisplayId, mId, {0, nullptr});
+    } else {
+        size_t rectCount = 0;
+        auto rectArray = damage.getArray(&rectCount);
+
+        std::vector<hwc_rect_t> hwcRects;
+        for (size_t rect = 0; rect < rectCount; ++rect) {
+            hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
+                    rectArray[rect].right, rectArray[rect].bottom});
+        }
+
+        hwc_region_t hwcRegion = {};
+        hwcRegion.numRects = rectCount;
+        hwcRegion.rects = hwcRects.data();
+
+        intError = mDevice.mSetLayerSurfaceDamage(mDevice.mHwcDevice,
+                mDisplayId, mId, hwcRegion);
+    }
+
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setBlendMode(BlendMode mode)
+{
+    auto intMode = static_cast<int32_t>(mode);
+    int32_t intError = mDevice.mSetLayerBlendMode(mDevice.mHwcDevice,
+            mDisplayId, mId, intMode);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setColor(hwc_color_t color)
+{
+    int32_t intError = mDevice.mSetLayerColor(mDevice.mHwcDevice, mDisplayId,
+            mId, color);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setCompositionType(Composition type)
+{
+    auto intType = static_cast<int32_t>(type);
+    int32_t intError = mDevice.mSetLayerCompositionType(mDevice.mHwcDevice,
+            mDisplayId, mId, intType);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setDataspace(android_dataspace_t dataspace)
+{
+    auto intDataspace = static_cast<int32_t>(dataspace);
+    int32_t intError = mDevice.mSetLayerDataspace(mDevice.mHwcDevice,
+            mDisplayId, mId, intDataspace);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setDisplayFrame(const Rect& frame)
+{
+    hwc_rect_t hwcRect{frame.left, frame.top, frame.right, frame.bottom};
+    int32_t intError = mDevice.mSetLayerDisplayFrame(mDevice.mHwcDevice,
+            mDisplayId, mId, hwcRect);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setPlaneAlpha(float alpha)
+{
+    int32_t intError = mDevice.mSetLayerPlaneAlpha(mDevice.mHwcDevice,
+            mDisplayId, mId, alpha);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setSidebandStream(const native_handle_t* stream)
+{
+    if (!mDevice.hasCapability(Capability::SidebandStream)) {
+        ALOGE("Attempted to call setSidebandStream without checking that the "
+                "device supports sideband streams");
+        return Error::Unsupported;
+    }
+    int32_t intError = mDevice.mSetLayerSidebandStream(mDevice.mHwcDevice,
+            mDisplayId, mId, stream);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setSourceCrop(const FloatRect& crop)
+{
+    hwc_frect_t hwcRect{crop.left, crop.top, crop.right, crop.bottom};
+    int32_t intError = mDevice.mSetLayerSourceCrop(mDevice.mHwcDevice,
+            mDisplayId, mId, hwcRect);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setTransform(Transform transform)
+{
+    auto intTransform = static_cast<int32_t>(transform);
+    int32_t intError = mDevice.mSetLayerTransform(mDevice.mHwcDevice,
+            mDisplayId, mId, intTransform);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setVisibleRegion(const Region& region)
+{
+    size_t rectCount = 0;
+    auto rectArray = region.getArray(&rectCount);
+
+    std::vector<hwc_rect_t> hwcRects;
+    for (size_t rect = 0; rect < rectCount; ++rect) {
+        hwcRects.push_back({rectArray[rect].left, rectArray[rect].top,
+                rectArray[rect].right, rectArray[rect].bottom});
+    }
+
+    hwc_region_t hwcRegion = {};
+    hwcRegion.numRects = rectCount;
+    hwcRegion.rects = hwcRects.data();
+
+    int32_t intError = mDevice.mSetLayerVisibleRegion(mDevice.mHwcDevice,
+            mDisplayId, mId, hwcRegion);
+    return static_cast<Error>(intError);
+}
+
+Error Layer::setZOrder(uint32_t z)
+{
+    int32_t intError = mDevice.mSetLayerZOrder(mDevice.mHwcDevice, mDisplayId,
+            mId, z);
+    return static_cast<Error>(intError);
+}
+
+} // namespace HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
new file mode 100644
index 0000000..e40602f
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -0,0 +1,396 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SF_HWC2_H
+#define ANDROID_SF_HWC2_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <ui/HdrCapabilities.h>
+#include <ui/mat4.h>
+
+#include <utils/Log.h>
+#include <utils/StrongPointer.h>
+#include <utils/Timers.h>
+
+#include <functional>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+    class Fence;
+    class FloatRect;
+    class GraphicBuffer;
+    class Rect;
+    class Region;
+}
+
+namespace HWC2 {
+
+class Display;
+class Layer;
+
+typedef std::function<void(std::shared_ptr<Display>, Connection)>
+        HotplugCallback;
+typedef std::function<void(std::shared_ptr<Display>)> RefreshCallback;
+typedef std::function<void(std::shared_ptr<Display>, nsecs_t)> VsyncCallback;
+
+class Device
+{
+public:
+    Device(hwc2_device_t* device);
+    ~Device();
+
+    friend class HWC2::Display;
+    friend class HWC2::Layer;
+
+    // Required by HWC2
+
+    std::string dump() const;
+
+    const std::vector<Capability>& getCapabilities() const {
+        return mCapabilities;
+    };
+
+    uint32_t getMaxVirtualDisplayCount() const;
+    Error createVirtualDisplay(uint32_t width, uint32_t height,
+            std::shared_ptr<Display>* outDisplay);
+
+    void registerHotplugCallback(HotplugCallback hotplug);
+    void registerRefreshCallback(RefreshCallback refresh);
+    void registerVsyncCallback(VsyncCallback vsync);
+
+    // For use by callbacks
+
+    void callHotplug(std::shared_ptr<Display> display, Connection connected);
+    void callRefresh(std::shared_ptr<Display> display);
+    void callVsync(std::shared_ptr<Display> display, nsecs_t timestamp);
+
+    // Other Device methods
+
+    // This will create a Display if one is not found, but it will not be marked
+    // as connected
+    std::shared_ptr<Display> getDisplayById(hwc2_display_t id);
+
+    bool hasCapability(HWC2::Capability capability) const;
+
+private:
+    // Initialization methods
+
+    template <typename PFN>
+    [[clang::warn_unused_result]] bool loadFunctionPointer(
+            FunctionDescriptor desc, PFN& outPFN) {
+        auto intDesc = static_cast<int32_t>(desc);
+        auto pfn = mHwcDevice->getFunction(mHwcDevice, intDesc);
+        if (pfn != nullptr) {
+            outPFN = reinterpret_cast<PFN>(pfn);
+            return true;
+        } else {
+            ALOGE("Failed to load function %s", to_string(desc).c_str());
+            return false;
+        }
+    }
+
+    template <typename PFN, typename HOOK>
+    void registerCallback(Callback callback, HOOK hook) {
+        static_assert(std::is_same<PFN, HOOK>::value,
+                "Incompatible function pointer");
+        auto intCallback = static_cast<int32_t>(callback);
+        auto callbackData = static_cast<hwc2_callback_data_t>(this);
+        auto pfn = reinterpret_cast<hwc2_function_pointer_t>(hook);
+        mRegisterCallback(mHwcDevice, intCallback, callbackData, pfn);
+    }
+
+    void loadCapabilities();
+    void loadFunctionPointers();
+    void registerCallbacks();
+
+    // For use by Display
+
+    void destroyVirtualDisplay(hwc2_display_t display);
+
+    // Member variables
+
+    hwc2_device_t* mHwcDevice;
+
+    // Device function pointers
+    HWC2_PFN_CREATE_VIRTUAL_DISPLAY mCreateVirtualDisplay;
+    HWC2_PFN_DESTROY_VIRTUAL_DISPLAY mDestroyVirtualDisplay;
+    HWC2_PFN_DUMP mDump;
+    HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT mGetMaxVirtualDisplayCount;
+    HWC2_PFN_REGISTER_CALLBACK mRegisterCallback;
+
+    // Display function pointers
+    HWC2_PFN_ACCEPT_DISPLAY_CHANGES mAcceptDisplayChanges;
+    HWC2_PFN_CREATE_LAYER mCreateLayer;
+    HWC2_PFN_DESTROY_LAYER mDestroyLayer;
+    HWC2_PFN_GET_ACTIVE_CONFIG mGetActiveConfig;
+    HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES mGetChangedCompositionTypes;
+    HWC2_PFN_GET_COLOR_MODES mGetColorModes;
+    HWC2_PFN_GET_DISPLAY_ATTRIBUTE mGetDisplayAttribute;
+    HWC2_PFN_GET_DISPLAY_CONFIGS mGetDisplayConfigs;
+    HWC2_PFN_GET_DISPLAY_NAME mGetDisplayName;
+    HWC2_PFN_GET_DISPLAY_REQUESTS mGetDisplayRequests;
+    HWC2_PFN_GET_DISPLAY_TYPE mGetDisplayType;
+    HWC2_PFN_GET_DOZE_SUPPORT mGetDozeSupport;
+    HWC2_PFN_GET_HDR_CAPABILITIES mGetHdrCapabilities;
+    HWC2_PFN_GET_RELEASE_FENCES mGetReleaseFences;
+    HWC2_PFN_PRESENT_DISPLAY mPresentDisplay;
+    HWC2_PFN_SET_ACTIVE_CONFIG mSetActiveConfig;
+    HWC2_PFN_SET_CLIENT_TARGET mSetClientTarget;
+    HWC2_PFN_SET_COLOR_MODE mSetColorMode;
+    HWC2_PFN_SET_COLOR_TRANSFORM mSetColorTransform;
+    HWC2_PFN_SET_OUTPUT_BUFFER mSetOutputBuffer;
+    HWC2_PFN_SET_POWER_MODE mSetPowerMode;
+    HWC2_PFN_SET_VSYNC_ENABLED mSetVsyncEnabled;
+    HWC2_PFN_VALIDATE_DISPLAY mValidateDisplay;
+
+    // Layer function pointers
+    HWC2_PFN_SET_CURSOR_POSITION mSetCursorPosition;
+    HWC2_PFN_SET_LAYER_BUFFER mSetLayerBuffer;
+    HWC2_PFN_SET_LAYER_SURFACE_DAMAGE mSetLayerSurfaceDamage;
+    HWC2_PFN_SET_LAYER_BLEND_MODE mSetLayerBlendMode;
+    HWC2_PFN_SET_LAYER_COLOR mSetLayerColor;
+    HWC2_PFN_SET_LAYER_COMPOSITION_TYPE mSetLayerCompositionType;
+    HWC2_PFN_SET_LAYER_DATASPACE mSetLayerDataspace;
+    HWC2_PFN_SET_LAYER_DISPLAY_FRAME mSetLayerDisplayFrame;
+    HWC2_PFN_SET_LAYER_PLANE_ALPHA mSetLayerPlaneAlpha;
+    HWC2_PFN_SET_LAYER_SIDEBAND_STREAM mSetLayerSidebandStream;
+    HWC2_PFN_SET_LAYER_SOURCE_CROP mSetLayerSourceCrop;
+    HWC2_PFN_SET_LAYER_TRANSFORM mSetLayerTransform;
+    HWC2_PFN_SET_LAYER_VISIBLE_REGION mSetLayerVisibleRegion;
+    HWC2_PFN_SET_LAYER_Z_ORDER mSetLayerZOrder;
+
+    std::vector<Capability> mCapabilities;
+    std::unordered_map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+
+    HotplugCallback mHotplug;
+    std::vector<std::pair<std::shared_ptr<Display>, Connection>>
+            mPendingHotplugs;
+    RefreshCallback mRefresh;
+    std::vector<std::shared_ptr<Display>> mPendingRefreshes;
+    VsyncCallback mVsync;
+    std::vector<std::pair<std::shared_ptr<Display>, nsecs_t>> mPendingVsyncs;
+};
+
+class Display : public std::enable_shared_from_this<Display>
+{
+public:
+    Display(Device& device, hwc2_display_t id);
+    ~Display();
+
+    friend class HWC2::Device;
+    friend class HWC2::Layer;
+
+    class Config
+    {
+    public:
+        class Builder
+        {
+        public:
+            Builder(Display& display, hwc2_config_t id);
+
+            std::shared_ptr<const Config> build() {
+                return std::const_pointer_cast<const Config>(
+                        std::move(mConfig));
+            }
+
+            Builder& setWidth(int32_t width) {
+                mConfig->mWidth = width;
+                return *this;
+            }
+            Builder& setHeight(int32_t height) {
+                mConfig->mHeight = height;
+                return *this;
+            }
+            Builder& setVsyncPeriod(int32_t vsyncPeriod) {
+                mConfig->mVsyncPeriod = vsyncPeriod;
+                return *this;
+            }
+            Builder& setDpiX(int32_t dpiX) {
+                if (dpiX == -1) {
+                    mConfig->mDpiX = getDefaultDensity();
+                } else {
+                    mConfig->mDpiX = dpiX / 1000.0f;
+                }
+                return *this;
+            }
+            Builder& setDpiY(int32_t dpiY) {
+                if (dpiY == -1) {
+                    mConfig->mDpiY = getDefaultDensity();
+                } else {
+                    mConfig->mDpiY = dpiY / 1000.0f;
+                }
+                return *this;
+            }
+
+        private:
+            float getDefaultDensity();
+            std::shared_ptr<Config> mConfig;
+        };
+
+        hwc2_display_t getDisplayId() const { return mDisplay.getId(); }
+        hwc2_config_t getId() const { return mId; }
+
+        int32_t getWidth() const { return mWidth; }
+        int32_t getHeight() const { return mHeight; }
+        nsecs_t getVsyncPeriod() const { return mVsyncPeriod; }
+        float getDpiX() const { return mDpiX; }
+        float getDpiY() const { return mDpiY; }
+
+    private:
+        Config(Display& display, hwc2_config_t id);
+
+        Display& mDisplay;
+        hwc2_config_t mId;
+
+        int32_t mWidth;
+        int32_t mHeight;
+        nsecs_t mVsyncPeriod;
+        float mDpiX;
+        float mDpiY;
+    };
+
+    // Required by HWC2
+
+    [[clang::warn_unused_result]] Error acceptChanges();
+    [[clang::warn_unused_result]] Error createLayer(
+            std::shared_ptr<Layer>* outLayer);
+    [[clang::warn_unused_result]] Error getActiveConfig(
+            std::shared_ptr<const Config>* outConfig) const;
+    [[clang::warn_unused_result]] Error getChangedCompositionTypes(
+            std::unordered_map<std::shared_ptr<Layer>, Composition>* outTypes);
+    [[clang::warn_unused_result]] Error getColorModes(
+            std::vector<int32_t>* outModes) const;
+
+    // Doesn't call into the HWC2 device, so no errors are possible
+    std::vector<std::shared_ptr<const Config>> getConfigs() const;
+
+    [[clang::warn_unused_result]] Error getName(std::string* outName) const;
+    [[clang::warn_unused_result]] Error getRequests(
+            DisplayRequest* outDisplayRequests,
+            std::unordered_map<std::shared_ptr<Layer>, LayerRequest>*
+                    outLayerRequests);
+    [[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
+    [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
+    [[clang::warn_unused_result]] Error getHdrCapabilities(
+            std::unique_ptr<android::HdrCapabilities>* outCapabilities) const;
+    [[clang::warn_unused_result]] Error getReleaseFences(
+            std::unordered_map<std::shared_ptr<Layer>,
+                    android::sp<android::Fence>>* outFences) const;
+    [[clang::warn_unused_result]] Error present(
+            android::sp<android::Fence>* outRetireFence);
+    [[clang::warn_unused_result]] Error setActiveConfig(
+            const std::shared_ptr<const Config>& config);
+    [[clang::warn_unused_result]] Error setClientTarget(
+            buffer_handle_t target,
+            const android::sp<android::Fence>& acquireFence,
+            android_dataspace_t dataspace);
+    [[clang::warn_unused_result]] Error setColorMode(int32_t mode);
+    [[clang::warn_unused_result]] Error setColorTransform(
+            const android::mat4& matrix, android_color_transform_t hint);
+    [[clang::warn_unused_result]] Error setOutputBuffer(
+            const android::sp<android::GraphicBuffer>& buffer,
+            const android::sp<android::Fence>& releaseFence);
+    [[clang::warn_unused_result]] Error setPowerMode(PowerMode mode);
+    [[clang::warn_unused_result]] Error setVsyncEnabled(Vsync enabled);
+    [[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes,
+            uint32_t* outNumRequests);
+
+    // Other Display methods
+
+    Device& getDevice() const { return mDevice; }
+    hwc2_display_t getId() const { return mId; }
+    bool isConnected() const { return mIsConnected; }
+
+private:
+    // For use by Device
+
+    // Virtual displays are always connected
+    void setVirtual() {
+        mIsVirtual = true;
+        mIsConnected = true;
+    }
+
+    void setConnected(bool connected) { mIsConnected = connected; }
+    int32_t getAttribute(hwc2_config_t configId, Attribute attribute);
+    void loadConfig(hwc2_config_t configId);
+    void loadConfigs();
+
+    // For use by Layer
+    void destroyLayer(hwc2_layer_t layerId);
+
+    // This may fail (and return a null pointer) if no layer with this ID exists
+    // on this display
+    std::shared_ptr<Layer> getLayerById(hwc2_layer_t id) const;
+
+    // Member variables
+
+    Device& mDevice;
+    hwc2_display_t mId;
+    bool mIsConnected;
+    bool mIsVirtual;
+    std::unordered_map<hwc2_layer_t, std::weak_ptr<Layer>> mLayers;
+    std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
+};
+
+class Layer
+{
+public:
+    Layer(const std::shared_ptr<Display>& display, hwc2_layer_t id);
+    ~Layer();
+
+    bool isAbandoned() const { return mDisplay.expired(); }
+    hwc2_layer_t getId() const { return mId; }
+
+    [[clang::warn_unused_result]] Error setCursorPosition(int32_t x, int32_t y);
+    [[clang::warn_unused_result]] Error setBuffer(buffer_handle_t buffer,
+            const android::sp<android::Fence>& acquireFence);
+    [[clang::warn_unused_result]] Error setSurfaceDamage(
+            const android::Region& damage);
+
+    [[clang::warn_unused_result]] Error setBlendMode(BlendMode mode);
+    [[clang::warn_unused_result]] Error setColor(hwc_color_t color);
+    [[clang::warn_unused_result]] Error setCompositionType(Composition type);
+    [[clang::warn_unused_result]] Error setDataspace(
+            android_dataspace_t dataspace);
+    [[clang::warn_unused_result]] Error setDisplayFrame(
+            const android::Rect& frame);
+    [[clang::warn_unused_result]] Error setPlaneAlpha(float alpha);
+    [[clang::warn_unused_result]] Error setSidebandStream(
+            const native_handle_t* stream);
+    [[clang::warn_unused_result]] Error setSourceCrop(
+            const android::FloatRect& crop);
+    [[clang::warn_unused_result]] Error setTransform(Transform transform);
+    [[clang::warn_unused_result]] Error setVisibleRegion(
+            const android::Region& region);
+    [[clang::warn_unused_result]] Error setZOrder(uint32_t z);
+
+private:
+    std::weak_ptr<Display> mDisplay;
+    hwc2_display_t mDisplayId;
+    Device& mDevice;
+    hwc2_layer_t mId;
+};
+
+} // namespace HWC2
+
+#endif // ANDROID_SF_HWC2_H
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
new file mode 100644
index 0000000..a90e074
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.cpp
@@ -0,0 +1,2649 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWC2On1Adapter"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "HWC2On1Adapter.h"
+
+#include <hardware/hwcomposer.h>
+#include <log/log.h>
+#include <utils/Trace.h>
+
+#include <cstdlib>
+#include <chrono>
+#include <inttypes.h>
+#include <sstream>
+
+using namespace std::chrono_literals;
+
+static bool operator==(const hwc_color_t& lhs, const hwc_color_t& rhs) {
+    return lhs.r == rhs.r &&
+            lhs.g == rhs.g &&
+            lhs.b == rhs.b &&
+            lhs.a == rhs.a;
+}
+
+static bool operator==(const hwc_rect_t& lhs, const hwc_rect_t& rhs) {
+    return lhs.left == rhs.left &&
+            lhs.top == rhs.top &&
+            lhs.right == rhs.right &&
+            lhs.bottom == rhs.bottom;
+}
+
+static bool operator==(const hwc_frect_t& lhs, const hwc_frect_t& rhs) {
+    return lhs.left == rhs.left &&
+            lhs.top == rhs.top &&
+            lhs.right == rhs.right &&
+            lhs.bottom == rhs.bottom;
+}
+
+template <typename T>
+static inline bool operator!=(const T& lhs, const T& rhs)
+{
+    return !(lhs == rhs);
+}
+
+static uint8_t getMinorVersion(struct hwc_composer_device_1* device)
+{
+    auto version = device->common.version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+    return (version >> 16) & 0xF;
+}
+
+template <typename PFN, typename T>
+static hwc2_function_pointer_t asFP(T function)
+{
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<hwc2_function_pointer_t>(function);
+}
+
+using namespace HWC2;
+
+static constexpr Attribute ColorTransform = static_cast<Attribute>(6);
+
+namespace android {
+
+void HWC2On1Adapter::DisplayContentsDeleter::operator()(
+        hwc_display_contents_1_t* contents)
+{
+    if (contents != nullptr) {
+        for (size_t l = 0; l < contents->numHwLayers; ++l) {
+            auto& layer = contents->hwLayers[l];
+            std::free(const_cast<hwc_rect_t*>(layer.visibleRegionScreen.rects));
+        }
+    }
+    std::free(contents);
+}
+
+class HWC2On1Adapter::Callbacks : public hwc_procs_t {
+    public:
+        Callbacks(HWC2On1Adapter& adapter) : mAdapter(adapter) {
+            invalidate = &invalidateHook;
+            vsync = &vsyncHook;
+            hotplug = &hotplugHook;
+        }
+
+        static void invalidateHook(const hwc_procs_t* procs) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Invalidate();
+        }
+
+        static void vsyncHook(const hwc_procs_t* procs, int display,
+                int64_t timestamp) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Vsync(display, timestamp);
+        }
+
+        static void hotplugHook(const hwc_procs_t* procs, int display,
+                int connected) {
+            auto callbacks = static_cast<const Callbacks*>(procs);
+            callbacks->mAdapter.hwc1Hotplug(display, connected);
+        }
+
+    private:
+        HWC2On1Adapter& mAdapter;
+};
+
+static int closeHook(hw_device_t* /*device*/)
+{
+    // Do nothing, since the real work is done in the class destructor, but we
+    // need to provide a valid function pointer for hwc2_close to call
+    return 0;
+}
+
+HWC2On1Adapter::HWC2On1Adapter(hwc_composer_device_1_t* hwc1Device)
+  : mDumpString(),
+    mHwc1Device(hwc1Device),
+    mHwc1MinorVersion(getMinorVersion(hwc1Device)),
+    mHwc1SupportsVirtualDisplays(false),
+    mHwc1Callbacks(std::make_unique<Callbacks>(*this)),
+    mCapabilities(),
+    mLayers(),
+    mHwc1VirtualDisplay(),
+    mStateMutex(),
+    mCallbacks(),
+    mHasPendingInvalidate(false),
+    mPendingVsyncs(),
+    mPendingHotplugs(),
+    mDisplays(),
+    mHwc1DisplayMap()
+{
+    common.close = closeHook;
+    getCapabilities = getCapabilitiesHook;
+    getFunction = getFunctionHook;
+    populateCapabilities();
+    populatePrimary();
+    mHwc1Device->registerProcs(mHwc1Device,
+            static_cast<const hwc_procs_t*>(mHwc1Callbacks.get()));
+}
+
+HWC2On1Adapter::~HWC2On1Adapter() {
+    hwc_close_1(mHwc1Device);
+}
+
+void HWC2On1Adapter::doGetCapabilities(uint32_t* outCount,
+        int32_t* outCapabilities)
+{
+    if (outCapabilities == nullptr) {
+        *outCount = mCapabilities.size();
+        return;
+    }
+
+    auto capabilityIter = mCapabilities.cbegin();
+    for (size_t written = 0; written < *outCount; ++written) {
+        if (capabilityIter == mCapabilities.cend()) {
+            return;
+        }
+        outCapabilities[written] = static_cast<int32_t>(*capabilityIter);
+        ++capabilityIter;
+    }
+}
+
+hwc2_function_pointer_t HWC2On1Adapter::doGetFunction(
+        FunctionDescriptor descriptor)
+{
+    switch (descriptor) {
+        // Device functions
+        case FunctionDescriptor::CreateVirtualDisplay:
+            return asFP<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+                    createVirtualDisplayHook);
+        case FunctionDescriptor::DestroyVirtualDisplay:
+            return asFP<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+                    destroyVirtualDisplayHook);
+        case FunctionDescriptor::Dump:
+            return asFP<HWC2_PFN_DUMP>(dumpHook);
+        case FunctionDescriptor::GetMaxVirtualDisplayCount:
+            return asFP<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+                    getMaxVirtualDisplayCountHook);
+        case FunctionDescriptor::RegisterCallback:
+            return asFP<HWC2_PFN_REGISTER_CALLBACK>(registerCallbackHook);
+
+        // Display functions
+        case FunctionDescriptor::AcceptDisplayChanges:
+            return asFP<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+                    displayHook<decltype(&Display::acceptChanges),
+                    &Display::acceptChanges>);
+        case FunctionDescriptor::CreateLayer:
+            return asFP<HWC2_PFN_CREATE_LAYER>(
+                    displayHook<decltype(&Display::createLayer),
+                    &Display::createLayer, hwc2_layer_t*>);
+        case FunctionDescriptor::DestroyLayer:
+            return asFP<HWC2_PFN_DESTROY_LAYER>(
+                    displayHook<decltype(&Display::destroyLayer),
+                    &Display::destroyLayer, hwc2_layer_t>);
+        case FunctionDescriptor::GetActiveConfig:
+            return asFP<HWC2_PFN_GET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::getActiveConfig),
+                    &Display::getActiveConfig, hwc2_config_t*>);
+        case FunctionDescriptor::GetChangedCompositionTypes:
+            return asFP<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+                    displayHook<decltype(&Display::getChangedCompositionTypes),
+                    &Display::getChangedCompositionTypes, uint32_t*,
+                    hwc2_layer_t*, int32_t*>);
+        case FunctionDescriptor::GetColorModes:
+            return asFP<HWC2_PFN_GET_COLOR_MODES>(
+                    displayHook<decltype(&Display::getColorModes),
+                    &Display::getColorModes, uint32_t*, int32_t*>);
+        case FunctionDescriptor::GetDisplayAttribute:
+            return asFP<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+                    getDisplayAttributeHook);
+        case FunctionDescriptor::GetDisplayConfigs:
+            return asFP<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+                    displayHook<decltype(&Display::getConfigs),
+                    &Display::getConfigs, uint32_t*, hwc2_config_t*>);
+        case FunctionDescriptor::GetDisplayName:
+            return asFP<HWC2_PFN_GET_DISPLAY_NAME>(
+                    displayHook<decltype(&Display::getName),
+                    &Display::getName, uint32_t*, char*>);
+        case FunctionDescriptor::GetDisplayRequests:
+            return asFP<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+                    displayHook<decltype(&Display::getRequests),
+                    &Display::getRequests, int32_t*, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::GetDisplayType:
+            return asFP<HWC2_PFN_GET_DISPLAY_TYPE>(
+                    displayHook<decltype(&Display::getType),
+                    &Display::getType, int32_t*>);
+        case FunctionDescriptor::GetDozeSupport:
+            return asFP<HWC2_PFN_GET_DOZE_SUPPORT>(
+                    displayHook<decltype(&Display::getDozeSupport),
+                    &Display::getDozeSupport, int32_t*>);
+        case FunctionDescriptor::GetHdrCapabilities:
+            return asFP<HWC2_PFN_GET_HDR_CAPABILITIES>(
+                    displayHook<decltype(&Display::getHdrCapabilities),
+                    &Display::getHdrCapabilities, uint32_t*, int32_t*, float*,
+                    float*, float*>);
+        case FunctionDescriptor::GetReleaseFences:
+            return asFP<HWC2_PFN_GET_RELEASE_FENCES>(
+                    displayHook<decltype(&Display::getReleaseFences),
+                    &Display::getReleaseFences, uint32_t*, hwc2_layer_t*,
+                    int32_t*>);
+        case FunctionDescriptor::PresentDisplay:
+            return asFP<HWC2_PFN_PRESENT_DISPLAY>(
+                    displayHook<decltype(&Display::present),
+                    &Display::present, int32_t*>);
+        case FunctionDescriptor::SetActiveConfig:
+            return asFP<HWC2_PFN_SET_ACTIVE_CONFIG>(
+                    displayHook<decltype(&Display::setActiveConfig),
+                    &Display::setActiveConfig, hwc2_config_t>);
+        case FunctionDescriptor::SetClientTarget:
+            return asFP<HWC2_PFN_SET_CLIENT_TARGET>(
+                    displayHook<decltype(&Display::setClientTarget),
+                    &Display::setClientTarget, buffer_handle_t, int32_t,
+                    int32_t>);
+        case FunctionDescriptor::SetColorMode:
+            return asFP<HWC2_PFN_SET_COLOR_MODE>(
+                    displayHook<decltype(&Display::setColorMode),
+                    &Display::setColorMode, int32_t>);
+        case FunctionDescriptor::SetColorTransform:
+            return asFP<HWC2_PFN_SET_COLOR_TRANSFORM>(setColorTransformHook);
+        case FunctionDescriptor::SetOutputBuffer:
+            return asFP<HWC2_PFN_SET_OUTPUT_BUFFER>(
+                    displayHook<decltype(&Display::setOutputBuffer),
+                    &Display::setOutputBuffer, buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetPowerMode:
+            return asFP<HWC2_PFN_SET_POWER_MODE>(setPowerModeHook);
+        case FunctionDescriptor::SetVsyncEnabled:
+            return asFP<HWC2_PFN_SET_VSYNC_ENABLED>(setVsyncEnabledHook);
+        case FunctionDescriptor::ValidateDisplay:
+            return asFP<HWC2_PFN_VALIDATE_DISPLAY>(
+                    displayHook<decltype(&Display::validate),
+                    &Display::validate, uint32_t*, uint32_t*>);
+
+        // Layer functions
+        case FunctionDescriptor::SetCursorPosition:
+            return asFP<HWC2_PFN_SET_CURSOR_POSITION>(
+                    layerHook<decltype(&Layer::setCursorPosition),
+                    &Layer::setCursorPosition, int32_t, int32_t>);
+        case FunctionDescriptor::SetLayerBuffer:
+            return asFP<HWC2_PFN_SET_LAYER_BUFFER>(
+                    layerHook<decltype(&Layer::setBuffer), &Layer::setBuffer,
+                    buffer_handle_t, int32_t>);
+        case FunctionDescriptor::SetLayerSurfaceDamage:
+            return asFP<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+                    layerHook<decltype(&Layer::setSurfaceDamage),
+                    &Layer::setSurfaceDamage, hwc_region_t>);
+
+        // Layer state functions
+        case FunctionDescriptor::SetLayerBlendMode:
+            return asFP<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+                    setLayerBlendModeHook);
+        case FunctionDescriptor::SetLayerColor:
+            return asFP<HWC2_PFN_SET_LAYER_COLOR>(
+                    layerHook<decltype(&Layer::setColor), &Layer::setColor,
+                    hwc_color_t>);
+        case FunctionDescriptor::SetLayerCompositionType:
+            return asFP<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+                    setLayerCompositionTypeHook);
+        case FunctionDescriptor::SetLayerDataspace:
+            return asFP<HWC2_PFN_SET_LAYER_DATASPACE>(setLayerDataspaceHook);
+        case FunctionDescriptor::SetLayerDisplayFrame:
+            return asFP<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+                    layerHook<decltype(&Layer::setDisplayFrame),
+                    &Layer::setDisplayFrame, hwc_rect_t>);
+        case FunctionDescriptor::SetLayerPlaneAlpha:
+            return asFP<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+                    layerHook<decltype(&Layer::setPlaneAlpha),
+                    &Layer::setPlaneAlpha, float>);
+        case FunctionDescriptor::SetLayerSidebandStream:
+            return asFP<HWC2_PFN_SET_LAYER_SIDEBAND_STREAM>(
+                    layerHook<decltype(&Layer::setSidebandStream),
+                    &Layer::setSidebandStream, const native_handle_t*>);
+        case FunctionDescriptor::SetLayerSourceCrop:
+            return asFP<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+                    layerHook<decltype(&Layer::setSourceCrop),
+                    &Layer::setSourceCrop, hwc_frect_t>);
+        case FunctionDescriptor::SetLayerTransform:
+            return asFP<HWC2_PFN_SET_LAYER_TRANSFORM>(setLayerTransformHook);
+        case FunctionDescriptor::SetLayerVisibleRegion:
+            return asFP<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+                    layerHook<decltype(&Layer::setVisibleRegion),
+                    &Layer::setVisibleRegion, hwc_region_t>);
+        case FunctionDescriptor::SetLayerZOrder:
+            return asFP<HWC2_PFN_SET_LAYER_Z_ORDER>(setLayerZOrderHook);
+
+        default:
+            ALOGE("doGetFunction: Unknown function descriptor: %d (%s)",
+                    static_cast<int32_t>(descriptor),
+                    to_string(descriptor).c_str());
+            return nullptr;
+    }
+}
+
+// Device functions
+
+Error HWC2On1Adapter::createVirtualDisplay(uint32_t width,
+        uint32_t height, hwc2_display_t* outDisplay)
+{
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (mHwc1VirtualDisplay) {
+        // We have already allocated our only HWC1 virtual display
+        ALOGE("createVirtualDisplay: HWC1 virtual display already allocated");
+        return Error::NoResources;
+    }
+
+    if (MAX_VIRTUAL_DISPLAY_DIMENSION != 0 &&
+            (width > MAX_VIRTUAL_DISPLAY_DIMENSION ||
+            height > MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+        ALOGE("createVirtualDisplay: Can't create a virtual display with"
+                " a dimension > %u (tried %u x %u)",
+                MAX_VIRTUAL_DISPLAY_DIMENSION, width, height);
+        return Error::NoResources;
+    }
+
+    mHwc1VirtualDisplay = std::make_shared<HWC2On1Adapter::Display>(*this,
+            HWC2::DisplayType::Virtual);
+    mHwc1VirtualDisplay->populateConfigs(width, height);
+    const auto displayId = mHwc1VirtualDisplay->getId();
+    mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL] = displayId;
+    mHwc1VirtualDisplay->setHwc1Id(HWC_DISPLAY_VIRTUAL);
+    mDisplays.emplace(displayId, mHwc1VirtualDisplay);
+    *outDisplay = displayId;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::destroyVirtualDisplay(hwc2_display_t displayId)
+{
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    if (!mHwc1VirtualDisplay || (mHwc1VirtualDisplay->getId() != displayId)) {
+        return Error::BadDisplay;
+    }
+
+    mHwc1VirtualDisplay.reset();
+    mHwc1DisplayMap.erase(HWC_DISPLAY_VIRTUAL);
+    mDisplays.erase(displayId);
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::dump(uint32_t* outSize, char* outBuffer)
+{
+    if (outBuffer != nullptr) {
+        auto copiedBytes = mDumpString.copy(outBuffer, *outSize);
+        *outSize = static_cast<uint32_t>(copiedBytes);
+        return;
+    }
+
+    std::stringstream output;
+
+    output << "-- HWC2On1Adapter --\n";
+
+    output << "Adapting to a HWC 1." << static_cast<int>(mHwc1MinorVersion) <<
+            " device\n";
+
+    // Attempt to acquire the lock for 1 second, but proceed without the lock
+    // after that, so we can still get some information if we're deadlocked
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex,
+            std::defer_lock);
+    lock.try_lock_for(1s);
+
+    if (mCapabilities.empty()) {
+        output << "Capabilities: None\n";
+    } else {
+        output << "Capabilities:\n";
+        for (auto capability : mCapabilities) {
+            output << "  " << to_string(capability) << '\n';
+        }
+    }
+
+    output << "Displays:\n";
+    for (const auto& element : mDisplays) {
+        const auto& display = element.second;
+        output << display->dump();
+    }
+    output << '\n';
+
+    // Release the lock before calling into HWC1, and since we no longer require
+    // mutual exclusion to access mCapabilities or mDisplays
+    lock.unlock();
+
+    if (mHwc1Device->dump) {
+        output << "HWC1 dump:\n";
+        std::vector<char> hwc1Dump(4096);
+        // Call with size - 1 to preserve a null character at the end
+        mHwc1Device->dump(mHwc1Device, hwc1Dump.data(),
+                static_cast<int>(hwc1Dump.size() - 1));
+        output << hwc1Dump.data();
+    }
+
+    mDumpString = output.str();
+    *outSize = static_cast<uint32_t>(mDumpString.size());
+}
+
+uint32_t HWC2On1Adapter::getMaxVirtualDisplayCount()
+{
+    return mHwc1SupportsVirtualDisplays ? 1 : 0;
+}
+
+static bool isValid(Callback descriptor) {
+    switch (descriptor) {
+        case Callback::Hotplug: // Fall-through
+        case Callback::Refresh: // Fall-through
+        case Callback::Vsync: return true;
+        default: return false;
+    }
+}
+
+Error HWC2On1Adapter::registerCallback(Callback descriptor,
+        hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer)
+{
+    if (!isValid(descriptor)) {
+        return Error::BadParameter;
+    }
+
+    ALOGV("registerCallback(%s, %p, %p)", to_string(descriptor).c_str(),
+            callbackData, pointer);
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    mCallbacks[descriptor] = {callbackData, pointer};
+
+    bool hasPendingInvalidate = false;
+    std::vector<hwc2_display_t> displayIds;
+    std::vector<std::pair<hwc2_display_t, int64_t>> pendingVsyncs;
+    std::vector<std::pair<hwc2_display_t, int>> pendingHotplugs;
+
+    if (descriptor == Callback::Refresh) {
+        hasPendingInvalidate = mHasPendingInvalidate;
+        if (hasPendingInvalidate) {
+            for (auto& displayPair : mDisplays) {
+                displayIds.emplace_back(displayPair.first);
+            }
+        }
+        mHasPendingInvalidate = false;
+    } else if (descriptor == Callback::Vsync) {
+        for (auto pending : mPendingVsyncs) {
+            auto hwc1DisplayId = pending.first;
+            if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+                ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d",
+                        hwc1DisplayId);
+                continue;
+            }
+            auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+            auto timestamp = pending.second;
+            pendingVsyncs.emplace_back(displayId, timestamp);
+        }
+        mPendingVsyncs.clear();
+    } else if (descriptor == Callback::Hotplug) {
+        // Hotplug the primary display
+        pendingHotplugs.emplace_back(mHwc1DisplayMap[HWC_DISPLAY_PRIMARY],
+                static_cast<int32_t>(Connection::Connected));
+
+        for (auto pending : mPendingHotplugs) {
+            auto hwc1DisplayId = pending.first;
+            if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+                ALOGE("hwc1Hotplug: Couldn't find display for HWC1 id %d",
+                        hwc1DisplayId);
+                continue;
+            }
+            auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+            auto connected = pending.second;
+            pendingHotplugs.emplace_back(displayId, connected);
+        }
+    }
+
+    // Call pending callbacks without the state lock held
+    lock.unlock();
+
+    if (hasPendingInvalidate) {
+        auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(pointer);
+        for (auto displayId : displayIds) {
+            refresh(callbackData, displayId);
+        }
+    }
+    if (!pendingVsyncs.empty()) {
+        auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
+        for (auto& pendingVsync : pendingVsyncs) {
+            vsync(callbackData, pendingVsync.first, pendingVsync.second);
+        }
+    }
+    if (!pendingHotplugs.empty()) {
+        auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(pointer);
+        for (auto& pendingHotplug : pendingHotplugs) {
+            hotplug(callbackData, pendingHotplug.first, pendingHotplug.second);
+        }
+    }
+    return Error::None;
+}
+
+// Display functions
+
+std::atomic<hwc2_display_t> HWC2On1Adapter::Display::sNextId(1);
+
+HWC2On1Adapter::Display::Display(HWC2On1Adapter& device, HWC2::DisplayType type)
+  : mId(sNextId++),
+    mDevice(device),
+    mDirtyCount(0),
+    mStateMutex(),
+    mZIsDirty(false),
+    mHwc1RequestedContents(nullptr),
+    mHwc1ReceivedContents(nullptr),
+    mRetireFence(),
+    mChanges(),
+    mHwc1Id(-1),
+    mConfigs(),
+    mActiveConfig(nullptr),
+    mName(),
+    mType(type),
+    mPowerMode(PowerMode::Off),
+    mVsyncEnabled(Vsync::Invalid),
+    mClientTarget(),
+    mOutputBuffer(),
+    mHasColorTransform(false),
+    mLayers(),
+    mHwc1LayerMap() {}
+
+Error HWC2On1Adapter::Display::acceptChanges()
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGV("[%" PRIu64 "] acceptChanges failed, not validated", mId);
+        return Error::NotValidated;
+    }
+
+    ALOGV("[%" PRIu64 "] acceptChanges", mId);
+
+    for (auto& change : mChanges->getTypeChanges()) {
+        auto layerId = change.first;
+        auto type = change.second;
+        auto layer = mDevice.mLayers[layerId];
+        layer->setCompositionType(type);
+    }
+
+    mChanges->clearTypeChanges();
+
+    mHwc1RequestedContents = std::move(mHwc1ReceivedContents);
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::createLayer(hwc2_layer_t* outLayerId)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    auto layer = *mLayers.emplace(std::make_shared<Layer>(*this));
+    mDevice.mLayers.emplace(std::make_pair(layer->getId(), layer));
+    *outLayerId = layer->getId();
+    ALOGV("[%" PRIu64 "] created layer %" PRIu64, mId, *outLayerId);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::destroyLayer(hwc2_layer_t layerId)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGV("[%" PRIu64 "] destroyLayer(%" PRIu64 ") failed: no such layer",
+                mId, layerId);
+        return Error::BadLayer;
+    }
+    const auto layer = mapLayer->second;
+    mDevice.mLayers.erase(mapLayer);
+    const auto zRange = mLayers.equal_range(layer);
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            current = mLayers.erase(current);
+            break;
+        }
+    }
+    ALOGV("[%" PRIu64 "] destroyed layer %" PRIu64, mId, layerId);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getActiveConfig(hwc2_config_t* outConfig)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mActiveConfig) {
+        ALOGV("[%" PRIu64 "] getActiveConfig --> %s", mId,
+                to_string(Error::BadConfig).c_str());
+        return Error::BadConfig;
+    }
+    auto configId = mActiveConfig->getId();
+    ALOGV("[%" PRIu64 "] getActiveConfig --> %u", mId, configId);
+    *outConfig = configId;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getAttribute(hwc2_config_t configId,
+        Attribute attribute, int32_t* outValue)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        ALOGV("[%" PRIu64 "] getAttribute failed: bad config (%u)", mId,
+                configId);
+        return Error::BadConfig;
+    }
+    *outValue = mConfigs[configId]->getAttribute(attribute);
+    ALOGV("[%" PRIu64 "] getAttribute(%u, %s) --> %d", mId, configId,
+            to_string(attribute).c_str(), *outValue);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getChangedCompositionTypes(
+        uint32_t* outNumElements, hwc2_layer_t* outLayers, int32_t* outTypes)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        ALOGE("[%" PRIu64 "] getChangedCompositionTypes failed: not validated",
+                mId);
+        return Error::NotValidated;
+    }
+
+    if ((outLayers == nullptr) || (outTypes == nullptr)) {
+        *outNumElements = mChanges->getTypeChanges().size();
+        return Error::None;
+    }
+
+    uint32_t numWritten = 0;
+    for (const auto& element : mChanges->getTypeChanges()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        auto layerId = element.first;
+        auto intType = static_cast<int32_t>(element.second);
+        ALOGV("Adding %" PRIu64 " %s", layerId,
+                to_string(element.second).c_str());
+        outLayers[numWritten] = layerId;
+        outTypes[numWritten] = intType;
+        ++numWritten;
+    }
+    *outNumElements = numWritten;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getColorModes(uint32_t* outNumModes,
+        int32_t* outModes)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outModes) {
+        *outNumModes = mColorModes.size();
+        return Error::None;
+    }
+    uint32_t numModes = std::min(*outNumModes,
+            static_cast<uint32_t>(mColorModes.size()));
+    std::copy_n(mColorModes.cbegin(), numModes, outModes);
+    *outNumModes = numModes;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getConfigs(uint32_t* outNumConfigs,
+        hwc2_config_t* outConfigs)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outConfigs) {
+        *outNumConfigs = mConfigs.size();
+        return Error::None;
+    }
+    uint32_t numWritten = 0;
+    for (const auto& config : mConfigs) {
+        if (numWritten == *outNumConfigs) {
+            break;
+        }
+        outConfigs[numWritten] = config->getId();
+        ++numWritten;
+    }
+    *outNumConfigs = numWritten;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getDozeSupport(int32_t* outSupport)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (mDevice.mHwc1MinorVersion < 4 || mHwc1Id != 0) {
+        *outSupport = 0;
+    } else {
+        *outSupport = 1;
+    }
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getHdrCapabilities(uint32_t* outNumTypes,
+        int32_t* /*outTypes*/, float* /*outMaxLuminance*/,
+        float* /*outMaxAverageLuminance*/, float* /*outMinLuminance*/)
+{
+    // This isn't supported on HWC1, so per the HWC2 header, return numTypes = 0
+    *outNumTypes = 0;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getName(uint32_t* outSize, char* outName)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!outName) {
+        *outSize = mName.size();
+        return Error::None;
+    }
+    auto numCopied = mName.copy(outName, *outSize);
+    *outSize = numCopied;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getReleaseFences(uint32_t* outNumElements,
+        hwc2_layer_t* outLayers, int32_t* outFences)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    uint32_t numWritten = 0;
+    bool outputsNonNull = (outLayers != nullptr) && (outFences != nullptr);
+    for (const auto& layer : mLayers) {
+        if (outputsNonNull && (numWritten == *outNumElements)) {
+            break;
+        }
+
+        auto releaseFence = layer->getReleaseFence();
+        if (releaseFence != Fence::NO_FENCE) {
+            if (outputsNonNull) {
+                outLayers[numWritten] = layer->getId();
+                outFences[numWritten] = releaseFence->dup();
+            }
+            ++numWritten;
+        }
+    }
+    *outNumElements = numWritten;
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getRequests(int32_t* outDisplayRequests,
+        uint32_t* outNumElements, hwc2_layer_t* outLayers,
+        int32_t* outLayerRequests)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges) {
+        return Error::NotValidated;
+    }
+
+    if (outLayers == nullptr || outLayerRequests == nullptr) {
+        *outNumElements = mChanges->getNumLayerRequests();
+        return Error::None;
+    }
+
+    *outDisplayRequests = mChanges->getDisplayRequests();
+    uint32_t numWritten = 0;
+    for (const auto& request : mChanges->getLayerRequests()) {
+        if (numWritten == *outNumElements) {
+            break;
+        }
+        outLayers[numWritten] = request.first;
+        outLayerRequests[numWritten] = static_cast<int32_t>(request.second);
+        ++numWritten;
+    }
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::getType(int32_t* outType)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    *outType = static_cast<int32_t>(mType);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::present(int32_t* outRetireFence)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (mChanges) {
+        Error error = mDevice.setAllDisplays();
+        if (error != Error::None) {
+            ALOGE("[%" PRIu64 "] present: setAllDisplaysFailed (%s)", mId,
+                    to_string(error).c_str());
+            return error;
+        }
+    }
+
+    *outRetireFence = mRetireFence.get()->dup();
+    ALOGV("[%" PRIu64 "] present returning retire fence %d", mId,
+            *outRetireFence);
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setActiveConfig(hwc2_config_t configId)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    auto config = getConfig(configId);
+    if (!config) {
+        return Error::BadConfig;
+    }
+    if (config == mActiveConfig) {
+        return Error::None;
+    }
+
+    if (mDevice.mHwc1MinorVersion >= 4) {
+        uint32_t hwc1Id = 0;
+        auto error = config->getHwc1IdForColorMode(mActiveColorMode, &hwc1Id);
+        if (error != Error::None) {
+            return error;
+        }
+
+        int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+                mHwc1Id, static_cast<int>(hwc1Id));
+        if (intError != 0) {
+            ALOGE("setActiveConfig: Failed to set active config on HWC1 (%d)",
+                intError);
+            return Error::BadConfig;
+        }
+        mActiveConfig = config;
+    }
+
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setClientTarget(buffer_handle_t target,
+        int32_t acquireFence, int32_t /*dataspace*/)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setClientTarget(%p, %d)", mId, target, acquireFence);
+    mClientTarget.setBuffer(target);
+    mClientTarget.setFence(acquireFence);
+    // dataspace can't be used by HWC1, so ignore it
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorMode(int32_t mode)
+{
+    std::unique_lock<std::recursive_mutex> lock (mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setColorMode(%d)", mId, mode);
+
+    if (mode == mActiveColorMode) {
+        return Error::None;
+    }
+    if (mColorModes.count(mode) == 0) {
+        ALOGE("[%" PRIu64 "] Mode %d not found in mColorModes", mId, mode);
+        return Error::Unsupported;
+    }
+
+    uint32_t hwc1Config = 0;
+    auto error = mActiveConfig->getHwc1IdForColorMode(mode, &hwc1Config);
+    if (error != Error::None) {
+        return error;
+    }
+
+    ALOGV("[%" PRIu64 "] Setting HWC1 config %u", mId, hwc1Config);
+    int intError = mDevice.mHwc1Device->setActiveConfig(mDevice.mHwc1Device,
+            mHwc1Id, hwc1Config);
+    if (intError != 0) {
+        ALOGE("[%" PRIu64 "] Failed to set HWC1 config (%d)", mId, intError);
+        return Error::Unsupported;
+    }
+
+    mActiveColorMode = mode;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setColorTransform(android_color_transform_t hint)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("%" PRIu64 "] setColorTransform(%d)", mId,
+            static_cast<int32_t>(hint));
+    mHasColorTransform = (hint != HAL_COLOR_TRANSFORM_IDENTITY);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::setOutputBuffer(buffer_handle_t buffer,
+        int32_t releaseFence)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] setOutputBuffer(%p, %d)", mId, buffer, releaseFence);
+    mOutputBuffer.setBuffer(buffer);
+    mOutputBuffer.setFence(releaseFence);
+    return Error::None;
+}
+
+static bool isValid(PowerMode mode)
+{
+    switch (mode) {
+        case PowerMode::Off: // Fall-through
+        case PowerMode::DozeSuspend: // Fall-through
+        case PowerMode::Doze: // Fall-through
+        case PowerMode::On: return true;
+        default: return false;
+    }
+}
+
+static int getHwc1PowerMode(PowerMode mode)
+{
+    switch (mode) {
+        case PowerMode::Off: return HWC_POWER_MODE_OFF;
+        case PowerMode::DozeSuspend: return HWC_POWER_MODE_DOZE_SUSPEND;
+        case PowerMode::Doze: return HWC_POWER_MODE_DOZE;
+        case PowerMode::On: return HWC_POWER_MODE_NORMAL;
+        default: return HWC_POWER_MODE_OFF;
+    }
+}
+
+Error HWC2On1Adapter::Display::setPowerMode(PowerMode mode)
+{
+    if (!isValid(mode)) {
+        return Error::BadParameter;
+    }
+    if (mode == mPowerMode) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    int error = 0;
+    if (mDevice.mHwc1MinorVersion < 4) {
+        error = mDevice.mHwc1Device->blank(mDevice.mHwc1Device, mHwc1Id,
+                mode == PowerMode::Off);
+    } else {
+        error = mDevice.mHwc1Device->setPowerMode(mDevice.mHwc1Device,
+                mHwc1Id, getHwc1PowerMode(mode));
+    }
+    ALOGE_IF(error != 0, "setPowerMode: Failed to set power mode on HWC1 (%d)",
+            error);
+
+    ALOGV("[%" PRIu64 "] setPowerMode(%s)", mId, to_string(mode).c_str());
+    mPowerMode = mode;
+    return Error::None;
+}
+
+static bool isValid(Vsync enable) {
+    switch (enable) {
+        case Vsync::Enable: // Fall-through
+        case Vsync::Disable: return true;
+        default: return false;
+    }
+}
+
+Error HWC2On1Adapter::Display::setVsyncEnabled(Vsync enable)
+{
+    if (!isValid(enable)) {
+        return Error::BadParameter;
+    }
+    if (enable == mVsyncEnabled) {
+        return Error::None;
+    }
+
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    int error = mDevice.mHwc1Device->eventControl(mDevice.mHwc1Device,
+            mHwc1Id, HWC_EVENT_VSYNC, enable == Vsync::Enable);
+    ALOGE_IF(error != 0, "setVsyncEnabled: Failed to set vsync on HWC1 (%d)",
+            error);
+
+    mVsyncEnabled = enable;
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Display::validate(uint32_t* outNumTypes,
+        uint32_t* outNumRequests)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] Entering validate", mId);
+
+    if (!mChanges) {
+        if (!mDevice.prepareAllDisplays()) {
+            return Error::BadDisplay;
+        }
+    }
+
+    *outNumTypes = mChanges->getNumTypes();
+    *outNumRequests = mChanges->getNumLayerRequests();
+    ALOGV("[%" PRIu64 "] validate --> %u types, %u requests", mId, *outNumTypes,
+            *outNumRequests);
+    for (auto request : mChanges->getTypeChanges()) {
+        ALOGV("Layer %" PRIu64 " --> %s", request.first,
+                to_string(request.second).c_str());
+    }
+    return *outNumTypes > 0 ? Error::HasChanges : Error::None;
+}
+
+// Display helpers
+
+Error HWC2On1Adapter::Display::updateLayerZ(hwc2_layer_t layerId, uint32_t z)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    const auto mapLayer = mDevice.mLayers.find(layerId);
+    if (mapLayer == mDevice.mLayers.end()) {
+        ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer", mId);
+        return Error::BadLayer;
+    }
+
+    const auto layer = mapLayer->second;
+    const auto zRange = mLayers.equal_range(layer);
+    bool layerOnDisplay = false;
+    for (auto current = zRange.first; current != zRange.second; ++current) {
+        if (**current == *layer) {
+            if ((*current)->getZ() == z) {
+                // Don't change anything if the Z hasn't changed
+                return Error::None;
+            }
+            current = mLayers.erase(current);
+            layerOnDisplay = true;
+            break;
+        }
+    }
+
+    if (!layerOnDisplay) {
+        ALOGE("[%" PRIu64 "] updateLayerZ failed to find layer on display",
+                mId);
+        return Error::BadLayer;
+    }
+
+    layer->setZ(z);
+    mLayers.emplace(std::move(layer));
+    mZIsDirty = true;
+
+    return Error::None;
+}
+
+static constexpr uint32_t ATTRIBUTES_WITH_COLOR[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_COLOR_TRANSFORM,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr uint32_t ATTRIBUTES_WITHOUT_COLOR[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+static constexpr size_t NUM_ATTRIBUTES_WITH_COLOR =
+        sizeof(ATTRIBUTES_WITH_COLOR) / sizeof(uint32_t);
+static_assert(sizeof(ATTRIBUTES_WITH_COLOR) > sizeof(ATTRIBUTES_WITHOUT_COLOR),
+        "Attribute tables have unexpected sizes");
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITH_COLOR[] = {
+    6, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+    0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+    1, // HWC_DISPLAY_WIDTH = 2,
+    2, // HWC_DISPLAY_HEIGHT = 3,
+    3, // HWC_DISPLAY_DPI_X = 4,
+    4, // HWC_DISPLAY_DPI_Y = 5,
+    5, // HWC_DISPLAY_COLOR_TRANSFORM = 6,
+};
+
+static constexpr uint32_t ATTRIBUTE_MAP_WITHOUT_COLOR[] = {
+    5, // HWC_DISPLAY_NO_ATTRIBUTE = 0
+    0, // HWC_DISPLAY_VSYNC_PERIOD = 1,
+    1, // HWC_DISPLAY_WIDTH = 2,
+    2, // HWC_DISPLAY_HEIGHT = 3,
+    3, // HWC_DISPLAY_DPI_X = 4,
+    4, // HWC_DISPLAY_DPI_Y = 5,
+};
+
+template <uint32_t attribute>
+static constexpr bool attributesMatch()
+{
+    bool match = (attribute ==
+            ATTRIBUTES_WITH_COLOR[ATTRIBUTE_MAP_WITH_COLOR[attribute]]);
+    if (attribute == HWC_DISPLAY_COLOR_TRANSFORM) {
+        return match;
+    }
+
+    return match && (attribute ==
+            ATTRIBUTES_WITHOUT_COLOR[ATTRIBUTE_MAP_WITHOUT_COLOR[attribute]]);
+}
+static_assert(attributesMatch<HWC_DISPLAY_VSYNC_PERIOD>(),
+        "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_WIDTH>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_HEIGHT>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_X>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_DPI_Y>(), "Tables out of sync");
+static_assert(attributesMatch<HWC_DISPLAY_COLOR_TRANSFORM>(),
+        "Tables out of sync");
+
+void HWC2On1Adapter::Display::populateConfigs()
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    ALOGV("[%" PRIu64 "] populateConfigs", mId);
+
+    if (mHwc1Id == -1) {
+        ALOGE("populateConfigs: HWC1 ID not set");
+        return;
+    }
+
+    const size_t MAX_NUM_CONFIGS = 128;
+    uint32_t configs[MAX_NUM_CONFIGS] = {};
+    size_t numConfigs = MAX_NUM_CONFIGS;
+    mDevice.mHwc1Device->getDisplayConfigs(mDevice.mHwc1Device, mHwc1Id,
+            configs, &numConfigs);
+
+    for (size_t c = 0; c < numConfigs; ++c) {
+        uint32_t hwc1ConfigId = configs[c];
+        auto newConfig = std::make_shared<Config>(*this);
+
+        int32_t values[NUM_ATTRIBUTES_WITH_COLOR] = {};
+        bool hasColor = true;
+        auto result = mDevice.mHwc1Device->getDisplayAttributes(
+                mDevice.mHwc1Device, mHwc1Id, hwc1ConfigId,
+                ATTRIBUTES_WITH_COLOR, values);
+        if (result != 0) {
+            mDevice.mHwc1Device->getDisplayAttributes(mDevice.mHwc1Device,
+                    mHwc1Id, hwc1ConfigId, ATTRIBUTES_WITHOUT_COLOR, values);
+            hasColor = false;
+        }
+
+        auto attributeMap = hasColor ?
+                ATTRIBUTE_MAP_WITH_COLOR : ATTRIBUTE_MAP_WITHOUT_COLOR;
+
+        newConfig->setAttribute(Attribute::VsyncPeriod,
+                values[attributeMap[HWC_DISPLAY_VSYNC_PERIOD]]);
+        newConfig->setAttribute(Attribute::Width,
+                values[attributeMap[HWC_DISPLAY_WIDTH]]);
+        newConfig->setAttribute(Attribute::Height,
+                values[attributeMap[HWC_DISPLAY_HEIGHT]]);
+        newConfig->setAttribute(Attribute::DpiX,
+                values[attributeMap[HWC_DISPLAY_DPI_X]]);
+        newConfig->setAttribute(Attribute::DpiY,
+                values[attributeMap[HWC_DISPLAY_DPI_Y]]);
+        if (hasColor) {
+            newConfig->setAttribute(ColorTransform,
+                    values[attributeMap[HWC_DISPLAY_COLOR_TRANSFORM]]);
+        }
+
+        // We can only do this after attempting to read the color transform
+        newConfig->setHwc1Id(hwc1ConfigId);
+
+        for (auto& existingConfig : mConfigs) {
+            if (existingConfig->merge(*newConfig)) {
+                ALOGV("Merged config %d with existing config %u: %s",
+                        hwc1ConfigId, existingConfig->getId(),
+                        existingConfig->toString().c_str());
+                newConfig.reset();
+                break;
+            }
+        }
+
+        // If it wasn't merged with any existing config, add it to the end
+        if (newConfig) {
+            newConfig->setId(static_cast<hwc2_config_t>(mConfigs.size()));
+            ALOGV("Found new config %u: %s", newConfig->getId(),
+                    newConfig->toString().c_str());
+            mConfigs.emplace_back(std::move(newConfig));
+        }
+    }
+
+    initializeActiveConfig();
+    populateColorModes();
+}
+
+void HWC2On1Adapter::Display::populateConfigs(uint32_t width, uint32_t height)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    mConfigs.emplace_back(std::make_shared<Config>(*this));
+    auto& config = mConfigs[0];
+
+    config->setAttribute(Attribute::Width, static_cast<int32_t>(width));
+    config->setAttribute(Attribute::Height, static_cast<int32_t>(height));
+    config->setHwc1Id(0);
+    config->setId(0);
+    mActiveConfig = config;
+}
+
+bool HWC2On1Adapter::Display::prepare()
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    // Only prepare display contents for displays HWC1 knows about
+    if (mHwc1Id == -1) {
+        return true;
+    }
+
+    // It doesn't make sense to prepare a display for which there is no active
+    // config, so return early
+    if (!mActiveConfig) {
+        ALOGE("[%" PRIu64 "] Attempted to prepare, but no config active", mId);
+        return false;
+    }
+
+    ALOGV("[%" PRIu64 "] Entering prepare", mId);
+
+    auto currentCount = mHwc1RequestedContents ?
+            mHwc1RequestedContents->numHwLayers : 0;
+    auto requiredCount = mLayers.size() + 1;
+    ALOGV("[%" PRIu64 "]   Requires %zd layers, %zd allocated in %p", mId,
+            requiredCount, currentCount, mHwc1RequestedContents.get());
+
+    bool layerCountChanged = (currentCount != requiredCount);
+    if (layerCountChanged) {
+        reallocateHwc1Contents();
+    }
+
+    bool applyAllState = false;
+    if (layerCountChanged || mZIsDirty) {
+        assignHwc1LayerIds();
+        mZIsDirty = false;
+        applyAllState = true;
+    }
+
+    mHwc1RequestedContents->retireFenceFd = -1;
+    mHwc1RequestedContents->flags = 0;
+    if (isDirty() || applyAllState) {
+        mHwc1RequestedContents->flags |= HWC_GEOMETRY_CHANGED;
+    }
+
+    for (auto& layer : mLayers) {
+        auto& hwc1Layer = mHwc1RequestedContents->hwLayers[layer->getHwc1Id()];
+        hwc1Layer.releaseFenceFd = -1;
+        layer->applyState(hwc1Layer, applyAllState);
+    }
+
+    mHwc1RequestedContents->outbuf = mOutputBuffer.getBuffer();
+    mHwc1RequestedContents->outbufAcquireFenceFd = mOutputBuffer.getFence();
+
+    prepareFramebufferTarget();
+
+    return true;
+}
+
+static void cloneHWCRegion(hwc_region_t& region)
+{
+    auto size = sizeof(hwc_rect_t) * region.numRects;
+    auto newRects = static_cast<hwc_rect_t*>(std::malloc(size));
+    std::copy_n(region.rects, region.numRects, newRects);
+    region.rects = newRects;
+}
+
+HWC2On1Adapter::Display::HWC1Contents
+        HWC2On1Adapter::Display::cloneRequestedContents() const
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    size_t size = sizeof(hwc_display_contents_1_t) +
+            sizeof(hwc_layer_1_t) * (mHwc1RequestedContents->numHwLayers);
+    auto contents = static_cast<hwc_display_contents_1_t*>(std::malloc(size));
+    std::memcpy(contents, mHwc1RequestedContents.get(), size);
+    for (size_t layerId = 0; layerId < contents->numHwLayers; ++layerId) {
+        auto& layer = contents->hwLayers[layerId];
+        // Deep copy the regions to avoid double-frees
+        cloneHWCRegion(layer.visibleRegionScreen);
+        cloneHWCRegion(layer.surfaceDamage);
+    }
+    return HWC1Contents(contents);
+}
+
+void HWC2On1Adapter::Display::setReceivedContents(HWC1Contents contents)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    mHwc1ReceivedContents = std::move(contents);
+
+    mChanges.reset(new Changes);
+
+    size_t numLayers = mHwc1ReceivedContents->numHwLayers;
+    for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+        const auto& receivedLayer = mHwc1ReceivedContents->hwLayers[hwc1Id];
+        if (mHwc1LayerMap.count(hwc1Id) == 0) {
+            ALOGE_IF(receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET,
+                    "setReceivedContents: HWC1 layer %zd doesn't have a"
+                    " matching HWC2 layer, and isn't the framebuffer target",
+                    hwc1Id);
+            continue;
+        }
+
+        Layer& layer = *mHwc1LayerMap[hwc1Id];
+        updateTypeChanges(receivedLayer, layer);
+        updateLayerRequests(receivedLayer, layer);
+    }
+}
+
+bool HWC2On1Adapter::Display::hasChanges() const
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    return mChanges != nullptr;
+}
+
+Error HWC2On1Adapter::Display::set(hwc_display_contents_1& hwcContents)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    if (!mChanges || (mChanges->getNumTypes() > 0)) {
+        ALOGE("[%" PRIu64 "] set failed: not validated", mId);
+        return Error::NotValidated;
+    }
+
+    // Set up the client/framebuffer target
+    auto numLayers = hwcContents.numHwLayers;
+
+    // Close acquire fences on FRAMEBUFFER layers, since they will not be used
+    // by HWC
+    for (size_t l = 0; l < numLayers - 1; ++l) {
+        auto& layer = hwcContents.hwLayers[l];
+        if (layer.compositionType == HWC_FRAMEBUFFER) {
+            ALOGV("Closing fence %d for layer %zd", layer.acquireFenceFd, l);
+            close(layer.acquireFenceFd);
+            layer.acquireFenceFd = -1;
+        }
+    }
+
+    auto& clientTargetLayer = hwcContents.hwLayers[numLayers - 1];
+    if (clientTargetLayer.compositionType == HWC_FRAMEBUFFER_TARGET) {
+        clientTargetLayer.handle = mClientTarget.getBuffer();
+        clientTargetLayer.acquireFenceFd = mClientTarget.getFence();
+    } else {
+        ALOGE("[%" PRIu64 "] set: last HWC layer wasn't FRAMEBUFFER_TARGET",
+                mId);
+    }
+
+    mChanges.reset();
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::Display::addRetireFence(int fenceFd)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    mRetireFence.add(fenceFd);
+}
+
+void HWC2On1Adapter::Display::addReleaseFences(
+        const hwc_display_contents_1_t& hwcContents)
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    size_t numLayers = hwcContents.numHwLayers;
+    for (size_t hwc1Id = 0; hwc1Id < numLayers; ++hwc1Id) {
+        const auto& receivedLayer = hwcContents.hwLayers[hwc1Id];
+        if (mHwc1LayerMap.count(hwc1Id) == 0) {
+            if (receivedLayer.compositionType != HWC_FRAMEBUFFER_TARGET) {
+                ALOGE("addReleaseFences: HWC1 layer %zd doesn't have a"
+                        " matching HWC2 layer, and isn't the framebuffer"
+                        " target", hwc1Id);
+            }
+            // Close the framebuffer target release fence since we will use the
+            // display retire fence instead
+            if (receivedLayer.releaseFenceFd != -1) {
+                close(receivedLayer.releaseFenceFd);
+            }
+            continue;
+        }
+
+        Layer& layer = *mHwc1LayerMap[hwc1Id];
+        ALOGV("Adding release fence %d to layer %" PRIu64,
+                receivedLayer.releaseFenceFd, layer.getId());
+        layer.addReleaseFence(receivedLayer.releaseFenceFd);
+    }
+}
+
+bool HWC2On1Adapter::Display::hasColorTransform() const
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+    return mHasColorTransform;
+}
+
+static std::string hwc1CompositionString(int32_t type)
+{
+    switch (type) {
+        case HWC_FRAMEBUFFER: return "Framebuffer";
+        case HWC_OVERLAY: return "Overlay";
+        case HWC_BACKGROUND: return "Background";
+        case HWC_FRAMEBUFFER_TARGET: return "FramebufferTarget";
+        case HWC_SIDEBAND: return "Sideband";
+        case HWC_CURSOR_OVERLAY: return "CursorOverlay";
+        default:
+            return std::string("Unknown (") + std::to_string(type) + ")";
+    }
+}
+
+static std::string hwc1TransformString(int32_t transform)
+{
+    switch (transform) {
+        case 0: return "None";
+        case HWC_TRANSFORM_FLIP_H: return "FlipH";
+        case HWC_TRANSFORM_FLIP_V: return "FlipV";
+        case HWC_TRANSFORM_ROT_90: return "Rotate90";
+        case HWC_TRANSFORM_ROT_180: return "Rotate180";
+        case HWC_TRANSFORM_ROT_270: return "Rotate270";
+        case HWC_TRANSFORM_FLIP_H_ROT_90: return "FlipHRotate90";
+        case HWC_TRANSFORM_FLIP_V_ROT_90: return "FlipVRotate90";
+        default:
+            return std::string("Unknown (") + std::to_string(transform) + ")";
+    }
+}
+
+static std::string hwc1BlendModeString(int32_t mode)
+{
+    switch (mode) {
+        case HWC_BLENDING_NONE: return "None";
+        case HWC_BLENDING_PREMULT: return "Premultiplied";
+        case HWC_BLENDING_COVERAGE: return "Coverage";
+        default:
+            return std::string("Unknown (") + std::to_string(mode) + ")";
+    }
+}
+
+static std::string rectString(hwc_rect_t rect)
+{
+    std::stringstream output;
+    output << "[" << rect.left << ", " << rect.top << ", ";
+    output << rect.right << ", " << rect.bottom << "]";
+    return output.str();
+}
+
+static std::string approximateFloatString(float f)
+{
+    if (static_cast<int32_t>(f) == f) {
+        return std::to_string(static_cast<int32_t>(f));
+    }
+    int32_t truncated = static_cast<int32_t>(f * 10);
+    bool approximate = (static_cast<float>(truncated) != f * 10);
+    const size_t BUFFER_SIZE = 32;
+    char buffer[BUFFER_SIZE] = {};
+    auto bytesWritten = snprintf(buffer, BUFFER_SIZE,
+            "%s%.1f", approximate ? "~" : "", f);
+    return std::string(buffer, bytesWritten);
+}
+
+static std::string frectString(hwc_frect_t frect)
+{
+    std::stringstream output;
+    output << "[" << approximateFloatString(frect.left) << ", ";
+    output << approximateFloatString(frect.top) << ", ";
+    output << approximateFloatString(frect.right) << ", ";
+    output << approximateFloatString(frect.bottom) << "]";
+    return output.str();
+}
+
+static std::string colorString(hwc_color_t color)
+{
+    std::stringstream output;
+    output << "RGBA [";
+    output << static_cast<int32_t>(color.r) << ", ";
+    output << static_cast<int32_t>(color.g) << ", ";
+    output << static_cast<int32_t>(color.b) << ", ";
+    output << static_cast<int32_t>(color.a) << "]";
+    return output.str();
+}
+
+static std::string alphaString(float f)
+{
+    const size_t BUFFER_SIZE = 8;
+    char buffer[BUFFER_SIZE] = {};
+    auto bytesWritten = snprintf(buffer, BUFFER_SIZE, "%.3f", f);
+    return std::string(buffer, bytesWritten);
+}
+
+static std::string to_string(const hwc_layer_1_t& hwcLayer,
+        int32_t hwc1MinorVersion)
+{
+    const char* fill = "          ";
+
+    std::stringstream output;
+
+    output << "  Composition: " <<
+            hwc1CompositionString(hwcLayer.compositionType);
+
+    if (hwcLayer.compositionType == HWC_BACKGROUND) {
+        output << "  Color: " << colorString(hwcLayer.backgroundColor) << '\n';
+    } else if (hwcLayer.compositionType == HWC_SIDEBAND) {
+        output << "  Stream: " << hwcLayer.sidebandStream << '\n';
+    } else {
+        output << "  Buffer: " << hwcLayer.handle << "/" <<
+                hwcLayer.acquireFenceFd << '\n';
+    }
+
+    output << fill << "Display frame: " << rectString(hwcLayer.displayFrame) <<
+            '\n';
+
+    output << fill << "Source crop: ";
+    if (hwc1MinorVersion >= 3) {
+        output << frectString(hwcLayer.sourceCropf) << '\n';
+    } else {
+        output << rectString(hwcLayer.sourceCropi) << '\n';
+    }
+
+    output << fill << "Transform: " << hwc1TransformString(hwcLayer.transform);
+    output << "  Blend mode: " << hwc1BlendModeString(hwcLayer.blending);
+    if (hwcLayer.planeAlpha != 0xFF) {
+        output << "  Alpha: " << alphaString(hwcLayer.planeAlpha / 255.0f);
+    }
+    output << '\n';
+
+    if (hwcLayer.hints != 0) {
+        output << fill << "Hints:";
+        if ((hwcLayer.hints & HWC_HINT_TRIPLE_BUFFER) != 0) {
+            output << " TripleBuffer";
+        }
+        if ((hwcLayer.hints & HWC_HINT_CLEAR_FB) != 0) {
+            output << " ClearFB";
+        }
+        output << '\n';
+    }
+
+    if (hwcLayer.flags != 0) {
+        output << fill << "Flags:";
+        if ((hwcLayer.flags & HWC_SKIP_LAYER) != 0) {
+            output << " SkipLayer";
+        }
+        if ((hwcLayer.flags & HWC_IS_CURSOR_LAYER) != 0) {
+            output << " IsCursorLayer";
+        }
+        output << '\n';
+    }
+
+    return output.str();
+}
+
+static std::string to_string(const hwc_display_contents_1_t& hwcContents,
+        int32_t hwc1MinorVersion)
+{
+    const char* fill = "      ";
+
+    std::stringstream output;
+    output << fill << "Geometry changed: " <<
+            ((hwcContents.flags & HWC_GEOMETRY_CHANGED) != 0 ? "Y\n" : "N\n");
+
+    output << fill << hwcContents.numHwLayers << " Layer" <<
+            ((hwcContents.numHwLayers == 1) ? "\n" : "s\n");
+    for (size_t layer = 0; layer < hwcContents.numHwLayers; ++layer) {
+        output << fill << "  Layer " << layer;
+        output << to_string(hwcContents.hwLayers[layer], hwc1MinorVersion);
+    }
+
+    if (hwcContents.outbuf != nullptr) {
+        output << fill << "Output buffer: " << hwcContents.outbuf << "/" <<
+                hwcContents.outbufAcquireFenceFd << '\n';
+    }
+
+    return output.str();
+}
+
+std::string HWC2On1Adapter::Display::dump() const
+{
+    std::unique_lock<std::recursive_mutex> lock(mStateMutex);
+
+    std::stringstream output;
+
+    output << "  Display " << mId << ": ";
+    output << to_string(mType) << "  ";
+    output << "HWC1 ID: " << mHwc1Id << "  ";
+    output << "Power mode: " << to_string(mPowerMode) << "  ";
+    output << "Vsync: " << to_string(mVsyncEnabled) << '\n';
+
+    output << "    Color modes [active]:";
+    for (const auto& mode : mColorModes) {
+        if (mode == mActiveColorMode) {
+            output << " [" << mode << ']';
+        } else {
+            output << " " << mode;
+        }
+    }
+    output << '\n';
+
+    output << "    " << mConfigs.size() << " Config" <<
+            (mConfigs.size() == 1 ? "" : "s") << " (* active)\n";
+    for (const auto& config : mConfigs) {
+        output << (config == mActiveConfig ? "    * " : "      ");
+        output << config->toString(true) << '\n';
+    }
+
+    output << "    " << mLayers.size() << " Layer" <<
+            (mLayers.size() == 1 ? "" : "s") << '\n';
+    for (const auto& layer : mLayers) {
+        output << layer->dump();
+    }
+
+    output << "    Client target: " << mClientTarget.getBuffer() << '\n';
+
+    if (mOutputBuffer.getBuffer() != nullptr) {
+        output << "    Output buffer: " << mOutputBuffer.getBuffer() << '\n';
+    }
+
+    if (mHwc1ReceivedContents) {
+        output << "    Last received HWC1 state\n";
+        output << to_string(*mHwc1ReceivedContents, mDevice.mHwc1MinorVersion);
+    } else if (mHwc1RequestedContents) {
+        output << "    Last requested HWC1 state\n";
+        output << to_string(*mHwc1RequestedContents, mDevice.mHwc1MinorVersion);
+    }
+
+    return output.str();
+}
+
+void HWC2On1Adapter::Display::Config::setAttribute(HWC2::Attribute attribute,
+        int32_t value)
+{
+    mAttributes[attribute] = value;
+}
+
+int32_t HWC2On1Adapter::Display::Config::getAttribute(Attribute attribute) const
+{
+    if (mAttributes.count(attribute) == 0) {
+        return -1;
+    }
+    return mAttributes.at(attribute);
+}
+
+void HWC2On1Adapter::Display::Config::setHwc1Id(uint32_t id)
+{
+    int32_t colorTransform = getAttribute(ColorTransform);
+    mHwc1Ids.emplace(colorTransform, id);
+}
+
+bool HWC2On1Adapter::Display::Config::hasHwc1Id(uint32_t id) const
+{
+    for (const auto& idPair : mHwc1Ids) {
+        if (id == idPair.second) {
+            return true;
+        }
+    }
+    return false;
+}
+
+int32_t HWC2On1Adapter::Display::Config::getColorModeForHwc1Id(
+        uint32_t id) const
+{
+    for (const auto& idPair : mHwc1Ids) {
+        if (id == idPair.second) {
+            return idPair.first;
+        }
+    }
+    return -1;
+}
+
+Error HWC2On1Adapter::Display::Config::getHwc1IdForColorMode(int32_t mode,
+        uint32_t* outId) const
+{
+    for (const auto& idPair : mHwc1Ids) {
+        if (mode == idPair.first) {
+            *outId = idPair.second;
+            return Error::None;
+        }
+    }
+    ALOGE("Unable to find HWC1 ID for color mode %d on config %u", mode, mId);
+    return Error::BadParameter;
+}
+
+bool HWC2On1Adapter::Display::Config::merge(const Config& other)
+{
+    auto attributes = {HWC2::Attribute::Width, HWC2::Attribute::Height,
+            HWC2::Attribute::VsyncPeriod, HWC2::Attribute::DpiX,
+            HWC2::Attribute::DpiY};
+    for (auto attribute : attributes) {
+        if (getAttribute(attribute) != other.getAttribute(attribute)) {
+            return false;
+        }
+    }
+    int32_t otherColorTransform = other.getAttribute(ColorTransform);
+    if (mHwc1Ids.count(otherColorTransform) != 0) {
+        ALOGE("Attempted to merge two configs (%u and %u) which appear to be "
+                "identical", mHwc1Ids.at(otherColorTransform),
+                other.mHwc1Ids.at(otherColorTransform));
+        return false;
+    }
+    mHwc1Ids.emplace(otherColorTransform,
+            other.mHwc1Ids.at(otherColorTransform));
+    return true;
+}
+
+std::set<int32_t> HWC2On1Adapter::Display::Config::getColorTransforms() const
+{
+    std::set<int32_t> colorTransforms;
+    for (const auto& idPair : mHwc1Ids) {
+        colorTransforms.emplace(idPair.first);
+    }
+    return colorTransforms;
+}
+
+std::string HWC2On1Adapter::Display::Config::toString(bool splitLine) const
+{
+    std::string output;
+
+    const size_t BUFFER_SIZE = 100;
+    char buffer[BUFFER_SIZE] = {};
+    auto writtenBytes = snprintf(buffer, BUFFER_SIZE,
+            "%u x %u", mAttributes.at(HWC2::Attribute::Width),
+            mAttributes.at(HWC2::Attribute::Height));
+    output.append(buffer, writtenBytes);
+
+    if (mAttributes.count(HWC2::Attribute::VsyncPeriod) != 0) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE, " @ %.1f Hz",
+                1e9 / mAttributes.at(HWC2::Attribute::VsyncPeriod));
+        output.append(buffer, writtenBytes);
+    }
+
+    if (mAttributes.count(HWC2::Attribute::DpiX) != 0 &&
+            mAttributes.at(HWC2::Attribute::DpiX) != -1) {
+        std::memset(buffer, 0, BUFFER_SIZE);
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", DPI: %.1f x %.1f",
+                mAttributes.at(HWC2::Attribute::DpiX) / 1000.0f,
+                mAttributes.at(HWC2::Attribute::DpiY) / 1000.0f);
+        output.append(buffer, writtenBytes);
+    }
+
+    std::memset(buffer, 0, BUFFER_SIZE);
+    if (splitLine) {
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                "\n        HWC1 ID/Color transform:");
+    } else {
+        writtenBytes = snprintf(buffer, BUFFER_SIZE,
+                ", HWC1 ID/Color transform:");
+    }
+    output.append(buffer, writtenBytes);
+
+
+    for (const auto& id : mHwc1Ids) {
+        int32_t colorTransform = id.first;
+        uint32_t hwc1Id = id.second;
+        std::memset(buffer, 0, BUFFER_SIZE);
+        if (colorTransform == mDisplay.mActiveColorMode) {
+            writtenBytes = snprintf(buffer, BUFFER_SIZE, " [%u/%d]", hwc1Id,
+                    colorTransform);
+        } else {
+            writtenBytes = snprintf(buffer, BUFFER_SIZE, " %u/%d", hwc1Id,
+                    colorTransform);
+        }
+        output.append(buffer, writtenBytes);
+    }
+
+    return output;
+}
+
+std::shared_ptr<const HWC2On1Adapter::Display::Config>
+        HWC2On1Adapter::Display::getConfig(hwc2_config_t configId) const
+{
+    if (configId > mConfigs.size() || !mConfigs[configId]->isOnDisplay(*this)) {
+        return nullptr;
+    }
+    return mConfigs[configId];
+}
+
+void HWC2On1Adapter::Display::populateColorModes()
+{
+    mColorModes = mConfigs[0]->getColorTransforms();
+    for (const auto& config : mConfigs) {
+        std::set<int32_t> intersection;
+        auto configModes = config->getColorTransforms();
+        std::set_intersection(mColorModes.cbegin(), mColorModes.cend(),
+                configModes.cbegin(), configModes.cend(),
+                std::inserter(intersection, intersection.begin()));
+        std::swap(intersection, mColorModes);
+    }
+}
+
+void HWC2On1Adapter::Display::initializeActiveConfig()
+{
+    if (mDevice.mHwc1Device->getActiveConfig == nullptr) {
+        ALOGV("getActiveConfig is null, choosing config 0");
+        mActiveConfig = mConfigs[0];
+        mActiveColorMode = -1;
+        return;
+    }
+
+    auto activeConfig = mDevice.mHwc1Device->getActiveConfig(
+            mDevice.mHwc1Device, mHwc1Id);
+    if (activeConfig >= 0) {
+        for (const auto& config : mConfigs) {
+            if (config->hasHwc1Id(activeConfig)) {
+                ALOGV("Setting active config to %d for HWC1 config %u",
+                        config->getId(), activeConfig);
+                mActiveConfig = config;
+                mActiveColorMode = config->getColorModeForHwc1Id(activeConfig);
+                break;
+            }
+        }
+        if (!mActiveConfig) {
+            ALOGV("Unable to find active HWC1 config %u, defaulting to "
+                    "config 0", activeConfig);
+            mActiveConfig = mConfigs[0];
+            mActiveColorMode = -1;
+        }
+    }
+}
+
+void HWC2On1Adapter::Display::reallocateHwc1Contents()
+{
+    // Allocate an additional layer for the framebuffer target
+    auto numLayers = mLayers.size() + 1;
+    size_t size = sizeof(hwc_display_contents_1_t) +
+            sizeof(hwc_layer_1_t) * numLayers;
+    ALOGV("[%" PRIu64 "] reallocateHwc1Contents creating %zd layer%s", mId,
+            numLayers, numLayers != 1 ? "s" : "");
+    auto contents =
+            static_cast<hwc_display_contents_1_t*>(std::calloc(size, 1));
+    contents->numHwLayers = numLayers;
+    mHwc1RequestedContents.reset(contents);
+}
+
+void HWC2On1Adapter::Display::assignHwc1LayerIds()
+{
+    mHwc1LayerMap.clear();
+    size_t nextHwc1Id = 0;
+    for (auto& layer : mLayers) {
+        mHwc1LayerMap[nextHwc1Id] = layer;
+        layer->setHwc1Id(nextHwc1Id++);
+    }
+}
+
+void HWC2On1Adapter::Display::updateTypeChanges(const hwc_layer_1_t& hwc1Layer,
+        const Layer& layer)
+{
+    auto layerId = layer.getId();
+    switch (hwc1Layer.compositionType) {
+        case HWC_FRAMEBUFFER:
+            if (layer.getCompositionType() != Composition::Client) {
+                mChanges->addTypeChange(layerId, Composition::Client);
+            }
+            break;
+        case HWC_OVERLAY:
+            if (layer.getCompositionType() != Composition::Device) {
+                mChanges->addTypeChange(layerId, Composition::Device);
+            }
+            break;
+        case HWC_BACKGROUND:
+            ALOGE_IF(layer.getCompositionType() != Composition::SolidColor,
+                    "updateTypeChanges: HWC1 requested BACKGROUND, but HWC2"
+                    " wasn't expecting SolidColor");
+            break;
+        case HWC_FRAMEBUFFER_TARGET:
+            // Do nothing, since it shouldn't be modified by HWC1
+            break;
+        case HWC_SIDEBAND:
+            ALOGE_IF(layer.getCompositionType() != Composition::Sideband,
+                    "updateTypeChanges: HWC1 requested SIDEBAND, but HWC2"
+                    " wasn't expecting Sideband");
+            break;
+        case HWC_CURSOR_OVERLAY:
+            ALOGE_IF(layer.getCompositionType() != Composition::Cursor,
+                    "updateTypeChanges: HWC1 requested CURSOR_OVERLAY, but"
+                    " HWC2 wasn't expecting Cursor");
+            break;
+    }
+}
+
+void HWC2On1Adapter::Display::updateLayerRequests(
+        const hwc_layer_1_t& hwc1Layer, const Layer& layer)
+{
+    if ((hwc1Layer.hints & HWC_HINT_CLEAR_FB) != 0) {
+        mChanges->addLayerRequest(layer.getId(),
+                LayerRequest::ClearClientTarget);
+    }
+}
+
+void HWC2On1Adapter::Display::prepareFramebufferTarget()
+{
+    // We check that mActiveConfig is valid in Display::prepare
+    int32_t width = mActiveConfig->getAttribute(Attribute::Width);
+    int32_t height = mActiveConfig->getAttribute(Attribute::Height);
+
+    auto& hwc1Target = mHwc1RequestedContents->hwLayers[mLayers.size()];
+    hwc1Target.compositionType = HWC_FRAMEBUFFER_TARGET;
+    hwc1Target.releaseFenceFd = -1;
+    hwc1Target.hints = 0;
+    hwc1Target.flags = 0;
+    hwc1Target.transform = 0;
+    hwc1Target.blending = HWC_BLENDING_PREMULT;
+    if (mDevice.getHwc1MinorVersion() < 3) {
+        hwc1Target.sourceCropi = {0, 0, width, height};
+    } else {
+        hwc1Target.sourceCropf = {0.0f, 0.0f, static_cast<float>(width),
+                static_cast<float>(height)};
+    }
+    hwc1Target.displayFrame = {0, 0, width, height};
+    hwc1Target.planeAlpha = 255;
+    hwc1Target.visibleRegionScreen.numRects = 1;
+    auto rects = static_cast<hwc_rect_t*>(std::malloc(sizeof(hwc_rect_t)));
+    rects[0].left = 0;
+    rects[0].top = 0;
+    rects[0].right = width;
+    rects[0].bottom = height;
+    hwc1Target.visibleRegionScreen.rects = rects;
+
+    // We will set this to the correct value in set
+    hwc1Target.acquireFenceFd = -1;
+}
+
+// Layer functions
+
+std::atomic<hwc2_layer_t> HWC2On1Adapter::Layer::sNextId(1);
+
+HWC2On1Adapter::Layer::Layer(Display& display)
+  : mId(sNextId++),
+    mDisplay(display),
+    mDirtyCount(0),
+    mBuffer(),
+    mSurfaceDamage(),
+    mBlendMode(*this, BlendMode::None),
+    mColor(*this, {0, 0, 0, 0}),
+    mCompositionType(*this, Composition::Invalid),
+    mDisplayFrame(*this, {0, 0, -1, -1}),
+    mPlaneAlpha(*this, 0.0f),
+    mSidebandStream(*this, nullptr),
+    mSourceCrop(*this, {0.0f, 0.0f, -1.0f, -1.0f}),
+    mTransform(*this, Transform::None),
+    mVisibleRegion(*this, std::vector<hwc_rect_t>()),
+    mZ(0),
+    mReleaseFence(),
+    mHwc1Id(0),
+    mHasUnsupportedDataspace(false),
+    mHasUnsupportedPlaneAlpha(false) {}
+
+bool HWC2On1Adapter::SortLayersByZ::operator()(
+        const std::shared_ptr<Layer>& lhs, const std::shared_ptr<Layer>& rhs)
+{
+    return lhs->getZ() < rhs->getZ();
+}
+
+Error HWC2On1Adapter::Layer::setBuffer(buffer_handle_t buffer,
+        int32_t acquireFence)
+{
+    ALOGV("Setting acquireFence to %d for layer %" PRIu64, acquireFence, mId);
+    mBuffer.setBuffer(buffer);
+    mBuffer.setFence(acquireFence);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCursorPosition(int32_t x, int32_t y)
+{
+    if (mCompositionType.getValue() != Composition::Cursor) {
+        return Error::BadLayer;
+    }
+
+    if (mDisplay.hasChanges()) {
+        return Error::NotValidated;
+    }
+
+    auto displayId = mDisplay.getHwc1Id();
+    auto hwc1Device = mDisplay.getDevice().getHwc1Device();
+    hwc1Device->setCursorPositionAsync(hwc1Device, displayId, x, y);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSurfaceDamage(hwc_region_t damage)
+{
+    mSurfaceDamage.resize(damage.numRects);
+    std::copy_n(damage.rects, damage.numRects, mSurfaceDamage.begin());
+    return Error::None;
+}
+
+// Layer state functions
+
+Error HWC2On1Adapter::Layer::setBlendMode(BlendMode mode)
+{
+    mBlendMode.setPending(mode);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setColor(hwc_color_t color)
+{
+    mColor.setPending(color);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setCompositionType(Composition type)
+{
+    mCompositionType.setPending(type);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDataspace(android_dataspace_t dataspace)
+{
+    mHasUnsupportedDataspace = (dataspace != HAL_DATASPACE_UNKNOWN);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setDisplayFrame(hwc_rect_t frame)
+{
+    mDisplayFrame.setPending(frame);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setPlaneAlpha(float alpha)
+{
+    mPlaneAlpha.setPending(alpha);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSidebandStream(const native_handle_t* stream)
+{
+    mSidebandStream.setPending(stream);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setSourceCrop(hwc_frect_t crop)
+{
+    mSourceCrop.setPending(crop);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setTransform(Transform transform)
+{
+    mTransform.setPending(transform);
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setVisibleRegion(hwc_region_t rawVisible)
+{
+    std::vector<hwc_rect_t> visible(rawVisible.rects,
+            rawVisible.rects + rawVisible.numRects);
+    mVisibleRegion.setPending(std::move(visible));
+    return Error::None;
+}
+
+Error HWC2On1Adapter::Layer::setZ(uint32_t z)
+{
+    mZ = z;
+    return Error::None;
+}
+
+void HWC2On1Adapter::Layer::addReleaseFence(int fenceFd)
+{
+    ALOGV("addReleaseFence %d to layer %" PRIu64, fenceFd, mId);
+    mReleaseFence.add(fenceFd);
+}
+
+const sp<Fence>& HWC2On1Adapter::Layer::getReleaseFence() const
+{
+    return mReleaseFence.get();
+}
+
+void HWC2On1Adapter::Layer::applyState(hwc_layer_1_t& hwc1Layer,
+        bool applyAllState)
+{
+    applyCommonState(hwc1Layer, applyAllState);
+    auto compositionType = mCompositionType.getPendingValue();
+    if (compositionType == Composition::SolidColor) {
+        applySolidColorState(hwc1Layer, applyAllState);
+    } else if (compositionType == Composition::Sideband) {
+        applySidebandState(hwc1Layer, applyAllState);
+    } else {
+        applyBufferState(hwc1Layer);
+    }
+    applyCompositionType(hwc1Layer, applyAllState);
+}
+
+// Layer dump helpers
+
+static std::string regionStrings(const std::vector<hwc_rect_t>& visibleRegion,
+        const std::vector<hwc_rect_t>& surfaceDamage)
+{
+    std::string regions;
+    regions += "        Visible Region";
+    regions.resize(40, ' ');
+    regions += "Surface Damage\n";
+
+    size_t numPrinted = 0;
+    size_t maxSize = std::max(visibleRegion.size(), surfaceDamage.size());
+    while (numPrinted < maxSize) {
+        std::string line("        ");
+        if (visibleRegion.empty() && numPrinted == 0) {
+            line += "None";
+        } else if (numPrinted < visibleRegion.size()) {
+            line += rectString(visibleRegion[numPrinted]);
+        }
+        line.resize(40, ' ');
+        if (surfaceDamage.empty() && numPrinted == 0) {
+            line += "None";
+        } else if (numPrinted < surfaceDamage.size()) {
+            line += rectString(surfaceDamage[numPrinted]);
+        }
+        line += '\n';
+        regions += line;
+        ++numPrinted;
+    }
+    return regions;
+}
+
+std::string HWC2On1Adapter::Layer::dump() const
+{
+    std::stringstream output;
+    const char* fill = "      ";
+
+    output << fill << to_string(mCompositionType.getPendingValue());
+    output << " Layer  HWC2/1: " << mId << "/" << mHwc1Id << "  ";
+    output << "Z: " << mZ;
+    if (mCompositionType.getValue() == HWC2::Composition::SolidColor) {
+        output << "  " << colorString(mColor.getValue());
+    } else if (mCompositionType.getValue() == HWC2::Composition::Sideband) {
+        output << "  Handle: " << mSidebandStream.getValue() << '\n';
+    } else {
+        output << "  Buffer: " << mBuffer.getBuffer() << "/" <<
+                mBuffer.getFence() << '\n';
+        output << fill << "  Display frame [LTRB]: " <<
+                rectString(mDisplayFrame.getValue()) << '\n';
+        output << fill << "  Source crop: " <<
+                frectString(mSourceCrop.getValue()) << '\n';
+        output << fill << "  Transform: " << to_string(mTransform.getValue());
+        output << "  Blend mode: " << to_string(mBlendMode.getValue());
+        if (mPlaneAlpha.getValue() != 1.0f) {
+            output << "  Alpha: " <<
+                alphaString(mPlaneAlpha.getValue()) << '\n';
+        } else {
+            output << '\n';
+        }
+        output << regionStrings(mVisibleRegion.getValue(), mSurfaceDamage);
+    }
+    return output.str();
+}
+
+static int getHwc1Blending(HWC2::BlendMode blendMode)
+{
+    switch (blendMode) {
+        case BlendMode::Coverage: return HWC_BLENDING_COVERAGE;
+        case BlendMode::Premultiplied: return HWC_BLENDING_PREMULT;
+        default: return HWC_BLENDING_NONE;
+    }
+}
+
+void HWC2On1Adapter::Layer::applyCommonState(hwc_layer_1_t& hwc1Layer,
+        bool applyAllState)
+{
+    auto minorVersion = mDisplay.getDevice().getHwc1MinorVersion();
+    if (applyAllState || mBlendMode.isDirty()) {
+        hwc1Layer.blending = getHwc1Blending(mBlendMode.getPendingValue());
+        mBlendMode.latch();
+    }
+    if (applyAllState || mDisplayFrame.isDirty()) {
+        hwc1Layer.displayFrame = mDisplayFrame.getPendingValue();
+        mDisplayFrame.latch();
+    }
+    if (applyAllState || mPlaneAlpha.isDirty()) {
+        auto pendingAlpha = mPlaneAlpha.getPendingValue();
+        if (minorVersion < 2) {
+            mHasUnsupportedPlaneAlpha = pendingAlpha < 1.0f;
+        } else {
+            hwc1Layer.planeAlpha =
+                    static_cast<uint8_t>(255.0f * pendingAlpha + 0.5f);
+        }
+        mPlaneAlpha.latch();
+    }
+    if (applyAllState || mSourceCrop.isDirty()) {
+        if (minorVersion < 3) {
+            auto pending = mSourceCrop.getPendingValue();
+            hwc1Layer.sourceCropi.left =
+                    static_cast<int32_t>(std::ceil(pending.left));
+            hwc1Layer.sourceCropi.top =
+                    static_cast<int32_t>(std::ceil(pending.top));
+            hwc1Layer.sourceCropi.right =
+                    static_cast<int32_t>(std::floor(pending.right));
+            hwc1Layer.sourceCropi.bottom =
+                    static_cast<int32_t>(std::floor(pending.bottom));
+        } else {
+            hwc1Layer.sourceCropf = mSourceCrop.getPendingValue();
+        }
+        mSourceCrop.latch();
+    }
+    if (applyAllState || mTransform.isDirty()) {
+        hwc1Layer.transform =
+                static_cast<uint32_t>(mTransform.getPendingValue());
+        mTransform.latch();
+    }
+    if (applyAllState || mVisibleRegion.isDirty()) {
+        auto& hwc1VisibleRegion = hwc1Layer.visibleRegionScreen;
+
+        std::free(const_cast<hwc_rect_t*>(hwc1VisibleRegion.rects));
+
+        auto pending = mVisibleRegion.getPendingValue();
+        hwc_rect_t* newRects = static_cast<hwc_rect_t*>(
+                std::malloc(sizeof(hwc_rect_t) * pending.size()));
+        std::copy(pending.begin(), pending.end(), newRects);
+        hwc1VisibleRegion.rects = const_cast<const hwc_rect_t*>(newRects);
+        hwc1VisibleRegion.numRects = pending.size();
+        mVisibleRegion.latch();
+    }
+}
+
+void HWC2On1Adapter::Layer::applySolidColorState(hwc_layer_1_t& hwc1Layer,
+        bool applyAllState)
+{
+    if (applyAllState || mColor.isDirty()) {
+        hwc1Layer.backgroundColor = mColor.getPendingValue();
+        mColor.latch();
+    }
+}
+
+void HWC2On1Adapter::Layer::applySidebandState(hwc_layer_1_t& hwc1Layer,
+        bool applyAllState)
+{
+    if (applyAllState || mSidebandStream.isDirty()) {
+        hwc1Layer.sidebandStream = mSidebandStream.getPendingValue();
+        mSidebandStream.latch();
+    }
+}
+
+void HWC2On1Adapter::Layer::applyBufferState(hwc_layer_1_t& hwc1Layer)
+{
+    hwc1Layer.handle = mBuffer.getBuffer();
+    hwc1Layer.acquireFenceFd = mBuffer.getFence();
+}
+
+void HWC2On1Adapter::Layer::applyCompositionType(hwc_layer_1_t& hwc1Layer,
+        bool applyAllState)
+{
+    // HWC1 never supports color transforms or dataspaces and only sometimes
+    // supports plane alpha (depending on the version). These require us to drop
+    // some or all layers to client composition.
+    if (mHasUnsupportedDataspace || mHasUnsupportedPlaneAlpha ||
+            mDisplay.hasColorTransform()) {
+        hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+        hwc1Layer.flags = HWC_SKIP_LAYER;
+        return;
+    }
+
+    if (applyAllState || mCompositionType.isDirty()) {
+        hwc1Layer.flags = 0;
+        switch (mCompositionType.getPendingValue()) {
+            case Composition::Client:
+                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                hwc1Layer.flags |= HWC_SKIP_LAYER;
+                break;
+            case Composition::Device:
+                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                break;
+            case Composition::SolidColor:
+                hwc1Layer.compositionType = HWC_BACKGROUND;
+                break;
+            case Composition::Cursor:
+                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                if (mDisplay.getDevice().getHwc1MinorVersion() >= 4) {
+                    hwc1Layer.hints |= HWC_IS_CURSOR_LAYER;
+                }
+                break;
+            case Composition::Sideband:
+                if (mDisplay.getDevice().getHwc1MinorVersion() < 4) {
+                    hwc1Layer.compositionType = HWC_SIDEBAND;
+                } else {
+                    hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                    hwc1Layer.flags |= HWC_SKIP_LAYER;
+                }
+                break;
+            default:
+                hwc1Layer.compositionType = HWC_FRAMEBUFFER;
+                hwc1Layer.flags |= HWC_SKIP_LAYER;
+                break;
+        }
+        ALOGV("Layer %" PRIu64 " %s set to %d", mId,
+                to_string(mCompositionType.getPendingValue()).c_str(),
+                hwc1Layer.compositionType);
+        ALOGV_IF(hwc1Layer.flags & HWC_SKIP_LAYER, "    and skipping");
+        mCompositionType.latch();
+    }
+}
+
+// Adapter helpers
+
+void HWC2On1Adapter::populateCapabilities()
+{
+    ALOGV("populateCapabilities");
+    if (mHwc1MinorVersion >= 3U) {
+        int supportedTypes = 0;
+        auto result = mHwc1Device->query(mHwc1Device,
+                HWC_DISPLAY_TYPES_SUPPORTED, &supportedTypes);
+        if ((result == 0) && ((supportedTypes & HWC_DISPLAY_VIRTUAL) != 0)) {
+            ALOGI("Found support for HWC virtual displays");
+            mHwc1SupportsVirtualDisplays = true;
+        }
+    }
+    if (mHwc1MinorVersion >= 4U) {
+        mCapabilities.insert(Capability::SidebandStream);
+    }
+}
+
+HWC2On1Adapter::Display* HWC2On1Adapter::getDisplay(hwc2_display_t id)
+{
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    auto display = mDisplays.find(id);
+    if (display == mDisplays.end()) {
+        return nullptr;
+    }
+
+    return display->second.get();
+}
+
+std::tuple<HWC2On1Adapter::Layer*, Error> HWC2On1Adapter::getLayer(
+        hwc2_display_t displayId, hwc2_layer_t layerId)
+{
+    auto display = getDisplay(displayId);
+    if (!display) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadDisplay);
+    }
+
+    auto layerEntry = mLayers.find(layerId);
+    if (layerEntry == mLayers.end()) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+
+    auto layer = layerEntry->second;
+    if (layer->getDisplay().getId() != displayId) {
+        return std::make_tuple(static_cast<Layer*>(nullptr), Error::BadLayer);
+    }
+    return std::make_tuple(layer.get(), Error::None);
+}
+
+void HWC2On1Adapter::populatePrimary()
+{
+    ALOGV("populatePrimary");
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    auto display =
+            std::make_shared<Display>(*this, HWC2::DisplayType::Physical);
+    mHwc1DisplayMap[HWC_DISPLAY_PRIMARY] = display->getId();
+    display->setHwc1Id(HWC_DISPLAY_PRIMARY);
+    display->populateConfigs();
+    mDisplays.emplace(display->getId(), std::move(display));
+}
+
+bool HWC2On1Adapter::prepareAllDisplays()
+{
+    ATRACE_CALL();
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    for (const auto& displayPair : mDisplays) {
+        auto& display = displayPair.second;
+        if (!display->prepare()) {
+            return false;
+        }
+    }
+
+    if (mHwc1DisplayMap.count(0) == 0) {
+        ALOGE("prepareAllDisplays: Unable to find primary HWC1 display");
+        return false;
+    }
+
+    // Always push the primary display
+    std::vector<HWC2On1Adapter::Display::HWC1Contents> requestedContents;
+    auto primaryDisplayId = mHwc1DisplayMap[HWC_DISPLAY_PRIMARY];
+    auto& primaryDisplay = mDisplays[primaryDisplayId];
+    auto primaryDisplayContents = primaryDisplay->cloneRequestedContents();
+    requestedContents.push_back(std::move(primaryDisplayContents));
+
+    // Push the external display, if present
+    if (mHwc1DisplayMap.count(HWC_DISPLAY_EXTERNAL) != 0) {
+        auto externalDisplayId = mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL];
+        auto& externalDisplay = mDisplays[externalDisplayId];
+        auto externalDisplayContents =
+                externalDisplay->cloneRequestedContents();
+        requestedContents.push_back(std::move(externalDisplayContents));
+    } else {
+        // Even if an external display isn't present, we still need to send
+        // at least two displays down to HWC1
+        requestedContents.push_back(nullptr);
+    }
+
+    // Push the hardware virtual display, if supported and present
+    if (mHwc1MinorVersion >= 3) {
+        if (mHwc1DisplayMap.count(HWC_DISPLAY_VIRTUAL) != 0) {
+            auto virtualDisplayId = mHwc1DisplayMap[HWC_DISPLAY_VIRTUAL];
+            auto& virtualDisplay = mDisplays[virtualDisplayId];
+            auto virtualDisplayContents =
+                    virtualDisplay->cloneRequestedContents();
+            requestedContents.push_back(std::move(virtualDisplayContents));
+        } else {
+            requestedContents.push_back(nullptr);
+        }
+    }
+
+    mHwc1Contents.clear();
+    for (auto& displayContents : requestedContents) {
+        mHwc1Contents.push_back(displayContents.get());
+        if (!displayContents) {
+            continue;
+        }
+
+        ALOGV("Display %zd layers:", mHwc1Contents.size() - 1);
+        for (size_t l = 0; l < displayContents->numHwLayers; ++l) {
+            auto& layer = displayContents->hwLayers[l];
+            ALOGV("  %zd: %d", l, layer.compositionType);
+        }
+    }
+
+    ALOGV("Calling HWC1 prepare");
+    {
+        ATRACE_NAME("HWC1 prepare");
+        mHwc1Device->prepare(mHwc1Device, mHwc1Contents.size(),
+                mHwc1Contents.data());
+    }
+
+    for (size_t c = 0; c < mHwc1Contents.size(); ++c) {
+        auto& contents = mHwc1Contents[c];
+        if (!contents) {
+            continue;
+        }
+        ALOGV("Display %zd layers:", c);
+        for (size_t l = 0; l < contents->numHwLayers; ++l) {
+            ALOGV("  %zd: %d", l, contents->hwLayers[l].compositionType);
+        }
+    }
+
+    // Return the received contents to their respective displays
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        display->setReceivedContents(std::move(requestedContents[hwc1Id]));
+    }
+
+    return true;
+}
+
+Error HWC2On1Adapter::setAllDisplays()
+{
+    ATRACE_CALL();
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // Make sure we're ready to validate
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        Error error = display->set(*mHwc1Contents[hwc1Id]);
+        if (error != Error::None) {
+            ALOGE("setAllDisplays: Failed to set display %zd: %s", hwc1Id,
+                    to_string(error).c_str());
+            return error;
+        }
+    }
+
+    ALOGV("Calling HWC1 set");
+    {
+        ATRACE_NAME("HWC1 set");
+        mHwc1Device->set(mHwc1Device, mHwc1Contents.size(),
+                mHwc1Contents.data());
+    }
+
+    // Add retire and release fences
+    for (size_t hwc1Id = 0; hwc1Id < mHwc1Contents.size(); ++hwc1Id) {
+        if (mHwc1Contents[hwc1Id] == nullptr) {
+            continue;
+        }
+
+        auto displayId = mHwc1DisplayMap[hwc1Id];
+        auto& display = mDisplays[displayId];
+        auto retireFenceFd = mHwc1Contents[hwc1Id]->retireFenceFd;
+        ALOGV("setAllDisplays: Adding retire fence %d to display %zd",
+                retireFenceFd, hwc1Id);
+        display->addRetireFence(mHwc1Contents[hwc1Id]->retireFenceFd);
+        display->addReleaseFences(*mHwc1Contents[hwc1Id]);
+    }
+
+    return Error::None;
+}
+
+void HWC2On1Adapter::hwc1Invalidate()
+{
+    ALOGV("Received hwc1Invalidate");
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered
+    if (mCallbacks.count(Callback::Refresh) == 0) {
+        mHasPendingInvalidate = true;
+        return;
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Refresh];
+    std::vector<hwc2_display_t> displays;
+    for (const auto& displayPair : mDisplays) {
+        displays.emplace_back(displayPair.first);
+    }
+
+    // Call back without the state lock held
+    lock.unlock();
+
+    auto refresh = reinterpret_cast<HWC2_PFN_REFRESH>(callbackInfo.pointer);
+    for (auto display : displays) {
+        refresh(callbackInfo.data, display);
+    }
+}
+
+void HWC2On1Adapter::hwc1Vsync(int hwc1DisplayId, int64_t timestamp)
+{
+    ALOGV("Received hwc1Vsync(%d, %" PRId64 ")", hwc1DisplayId, timestamp);
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered
+    if (mCallbacks.count(Callback::Vsync) == 0) {
+        mPendingVsyncs.emplace_back(hwc1DisplayId, timestamp);
+        return;
+    }
+
+    if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+        ALOGE("hwc1Vsync: Couldn't find display for HWC1 id %d", hwc1DisplayId);
+        return;
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Vsync];
+    auto displayId = mHwc1DisplayMap[hwc1DisplayId];
+
+    // Call back without the state lock held
+    lock.unlock();
+
+    auto vsync = reinterpret_cast<HWC2_PFN_VSYNC>(callbackInfo.pointer);
+    vsync(callbackInfo.data, displayId, timestamp);
+}
+
+void HWC2On1Adapter::hwc1Hotplug(int hwc1DisplayId, int connected)
+{
+    ALOGV("Received hwc1Hotplug(%d, %d)", hwc1DisplayId, connected);
+
+    if (hwc1DisplayId != HWC_DISPLAY_EXTERNAL) {
+        ALOGE("hwc1Hotplug: Received hotplug for non-external display");
+        return;
+    }
+
+    std::unique_lock<std::recursive_timed_mutex> lock(mStateMutex);
+
+    // If the HWC2-side callback hasn't been registered yet, buffer this until
+    // it is registered
+    if (mCallbacks.count(Callback::Hotplug) == 0) {
+        mPendingHotplugs.emplace_back(hwc1DisplayId, connected);
+        return;
+    }
+
+    hwc2_display_t displayId = UINT64_MAX;
+    if (mHwc1DisplayMap.count(hwc1DisplayId) == 0) {
+        if (connected == 0) {
+            ALOGW("hwc1Hotplug: Received disconnect for unconnected display");
+            return;
+        }
+
+        // Create a new display on connect
+        auto display = std::make_shared<HWC2On1Adapter::Display>(*this,
+                HWC2::DisplayType::Physical);
+        display->setHwc1Id(HWC_DISPLAY_EXTERNAL);
+        display->populateConfigs();
+        displayId = display->getId();
+        mHwc1DisplayMap[HWC_DISPLAY_EXTERNAL] = displayId;
+        mDisplays.emplace(displayId, std::move(display));
+    } else {
+        if (connected != 0) {
+            ALOGW("hwc1Hotplug: Received connect for previously connected "
+                    "display");
+            return;
+        }
+
+        // Disconnect an existing display
+        displayId = mHwc1DisplayMap[hwc1DisplayId];
+        mHwc1DisplayMap.erase(HWC_DISPLAY_EXTERNAL);
+        mDisplays.erase(displayId);
+    }
+
+    const auto& callbackInfo = mCallbacks[Callback::Hotplug];
+
+    // Call back without the state lock held
+    lock.unlock();
+
+    auto hotplug = reinterpret_cast<HWC2_PFN_HOTPLUG>(callbackInfo.pointer);
+    auto hwc2Connected = (connected == 0) ?
+            HWC2::Connection::Disconnected : HWC2::Connection::Connected;
+    hotplug(callbackInfo.data, displayId, static_cast<int32_t>(hwc2Connected));
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
new file mode 100644
index 0000000..caeb188
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWC2On1Adapter.h
@@ -0,0 +1,680 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SF_HWC2_ON_1_ADAPTER_H
+#define ANDROID_SF_HWC2_ON_1_ADAPTER_H
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include <ui/Fence.h>
+
+#include <atomic>
+#include <map>
+#include <mutex>
+#include <queue>
+#include <set>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+
+namespace android {
+
+class HWC2On1Adapter : public hwc2_device_t
+{
+public:
+    HWC2On1Adapter(struct hwc_composer_device_1* hwc1Device);
+    ~HWC2On1Adapter();
+
+    struct hwc_composer_device_1* getHwc1Device() const { return mHwc1Device; }
+    uint8_t getHwc1MinorVersion() const { return mHwc1MinorVersion; }
+
+private:
+    static inline HWC2On1Adapter* getAdapter(hwc2_device_t* device) {
+        return static_cast<HWC2On1Adapter*>(device);
+    }
+
+    // getCapabilities
+
+    void doGetCapabilities(uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities);
+    static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
+            int32_t* /*hwc2_capability_t*/ outCapabilities) {
+        getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
+    }
+
+    // getFunction
+
+    hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
+    static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
+            int32_t intDesc) {
+        auto descriptor = static_cast<HWC2::FunctionDescriptor>(intDesc);
+        return getAdapter(device)->doGetFunction(descriptor);
+    }
+
+    // Device functions
+
+    HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
+            hwc2_display_t* outDisplay);
+    static int32_t createVirtualDisplayHook(hwc2_device_t* device,
+            uint32_t width, uint32_t height, hwc2_display_t* outDisplay) {
+        auto error = getAdapter(device)->createVirtualDisplay(width, height,
+                outDisplay);
+        return static_cast<int32_t>(error);
+    }
+
+    HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
+    static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
+            hwc2_display_t display) {
+        auto error = getAdapter(device)->destroyVirtualDisplay(display);
+        return static_cast<int32_t>(error);
+    }
+
+    std::string mDumpString;
+    void dump(uint32_t* outSize, char* outBuffer);
+    static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
+            char* outBuffer) {
+        getAdapter(device)->dump(outSize, outBuffer);
+    }
+
+    uint32_t getMaxVirtualDisplayCount();
+    static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
+        return getAdapter(device)->getMaxVirtualDisplayCount();
+    }
+
+    HWC2::Error registerCallback(HWC2::Callback descriptor,
+            hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
+    static int32_t registerCallbackHook(hwc2_device_t* device,
+            int32_t intDesc, hwc2_callback_data_t callbackData,
+            hwc2_function_pointer_t pointer) {
+        auto descriptor = static_cast<HWC2::Callback>(intDesc);
+        auto error = getAdapter(device)->registerCallback(descriptor,
+                callbackData, pointer);
+        return static_cast<int32_t>(error);
+    }
+
+    // Display functions
+
+    class Layer;
+
+    class SortLayersByZ {
+        public:
+            bool operator()(const std::shared_ptr<Layer>& lhs,
+                    const std::shared_ptr<Layer>& rhs);
+    };
+
+    class DisplayContentsDeleter {
+        public:
+            void operator()(struct hwc_display_contents_1* contents);
+    };
+
+    class DeferredFence {
+        public:
+            DeferredFence()
+              : mMutex(),
+                mFences({Fence::NO_FENCE, Fence::NO_FENCE}) {}
+
+            void add(int32_t fenceFd) {
+                mFences.emplace(new Fence(fenceFd));
+                mFences.pop();
+            }
+
+            const sp<Fence>& get() const {
+                return mFences.front();
+            }
+
+        private:
+            mutable std::mutex mMutex;
+            std::queue<sp<Fence>> mFences;
+    };
+
+    class FencedBuffer {
+        public:
+            FencedBuffer() : mBuffer(nullptr), mFence(Fence::NO_FENCE) {}
+
+            void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
+            void setFence(int fenceFd) { mFence = new Fence(fenceFd); }
+
+            buffer_handle_t getBuffer() const { return mBuffer; }
+            int getFence() const { return mFence->dup(); }
+
+        private:
+            buffer_handle_t mBuffer;
+            sp<Fence> mFence;
+    };
+
+    class Display {
+        public:
+            typedef std::unique_ptr<hwc_display_contents_1,
+                    DisplayContentsDeleter> HWC1Contents;
+
+            Display(HWC2On1Adapter& device, HWC2::DisplayType type);
+
+            hwc2_display_t getId() const { return mId; }
+            HWC2On1Adapter& getDevice() const { return mDevice; }
+
+            // Does not require locking because it is set before adding the
+            // Displays to the Adapter's list of displays
+            void setHwc1Id(int32_t id) { mHwc1Id = id; }
+            int32_t getHwc1Id() const { return mHwc1Id; }
+
+            void incDirty() { ++mDirtyCount; }
+            void decDirty() { --mDirtyCount; }
+            bool isDirty() const { return mDirtyCount > 0 || mZIsDirty; }
+
+            // HWC2 Display functions
+            HWC2::Error acceptChanges();
+            HWC2::Error createLayer(hwc2_layer_t* outLayerId);
+            HWC2::Error destroyLayer(hwc2_layer_t layerId);
+            HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
+            HWC2::Error getAttribute(hwc2_config_t configId,
+                    HWC2::Attribute attribute, int32_t* outValue);
+            HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
+                    hwc2_layer_t* outLayers, int32_t* outTypes);
+            HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
+            HWC2::Error getConfigs(uint32_t* outNumConfigs,
+                    hwc2_config_t* outConfigIds);
+            HWC2::Error getDozeSupport(int32_t* outSupport);
+            HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
+                    int32_t* outTypes, float* outMaxLuminance,
+                    float* outMaxAverageLuminance, float* outMinLuminance);
+            HWC2::Error getName(uint32_t* outSize, char* outName);
+            HWC2::Error getReleaseFences(uint32_t* outNumElements,
+                    hwc2_layer_t* outLayers, int32_t* outFences);
+            HWC2::Error getRequests(int32_t* outDisplayRequests,
+                    uint32_t* outNumElements, hwc2_layer_t* outLayers,
+                    int32_t* outLayerRequests);
+            HWC2::Error getType(int32_t* outType);
+            HWC2::Error present(int32_t* outRetireFence);
+            HWC2::Error setActiveConfig(hwc2_config_t configId);
+            HWC2::Error setClientTarget(buffer_handle_t target,
+                    int32_t acquireFence, int32_t dataspace);
+            HWC2::Error setColorMode(int32_t mode);
+            HWC2::Error setColorTransform(android_color_transform_t hint);
+            HWC2::Error setOutputBuffer(buffer_handle_t buffer,
+                    int32_t releaseFence);
+            HWC2::Error setPowerMode(HWC2::PowerMode mode);
+            HWC2::Error setVsyncEnabled(HWC2::Vsync enabled);
+            HWC2::Error validate(uint32_t* outNumTypes,
+                    uint32_t* outNumRequests);
+
+            HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
+
+            // Read configs from HWC1 device
+            void populateConfigs();
+
+            // Set configs for a virtual display
+            void populateConfigs(uint32_t width, uint32_t height);
+
+            bool prepare();
+            HWC1Contents cloneRequestedContents() const;
+            void setReceivedContents(HWC1Contents contents);
+            bool hasChanges() const;
+            HWC2::Error set(hwc_display_contents_1& hwcContents);
+            void addRetireFence(int fenceFd);
+            void addReleaseFences(const hwc_display_contents_1& hwcContents);
+
+            bool hasColorTransform() const;
+
+            std::string dump() const;
+
+        private:
+            class Config {
+                public:
+                    Config(Display& display)
+                      : mDisplay(display),
+                        mAttributes() {}
+
+                    bool isOnDisplay(const Display& display) const {
+                        return display.getId() == mDisplay.getId();
+                    }
+
+                    void setAttribute(HWC2::Attribute attribute, int32_t value);
+                    int32_t getAttribute(HWC2::Attribute attribute) const;
+
+                    void setHwc1Id(uint32_t id);
+                    bool hasHwc1Id(uint32_t id) const;
+                    int32_t getColorModeForHwc1Id(uint32_t id) const;
+                    HWC2::Error getHwc1IdForColorMode(int32_t mode,
+                            uint32_t* outId) const;
+
+                    void setId(hwc2_config_t id) { mId = id; }
+                    hwc2_config_t getId() const { return mId; }
+
+                    // Attempts to merge two configs that differ only in color
+                    // mode. Returns whether the merge was successful
+                    bool merge(const Config& other);
+
+                    std::set<int32_t> getColorTransforms() const;
+
+                    // splitLine divides the output into two lines suitable for
+                    // dumpsys SurfaceFlinger
+                    std::string toString(bool splitLine = false) const;
+
+                private:
+                    Display& mDisplay;
+                    hwc2_config_t mId;
+                    std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
+
+                    // Maps from color transform to HWC1 config ID
+                    std::unordered_map<int32_t, uint32_t> mHwc1Ids;
+            };
+
+            class Changes {
+                public:
+                    uint32_t getNumTypes() const {
+                        return static_cast<uint32_t>(mTypeChanges.size());
+                    }
+
+                    uint32_t getNumLayerRequests() const {
+                        return static_cast<uint32_t>(mLayerRequests.size());
+                    }
+
+                    const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
+                            getTypeChanges() const {
+                        return mTypeChanges;
+                    }
+
+                    const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
+                            getLayerRequests() const {
+                        return mLayerRequests;
+                    }
+
+                    int32_t getDisplayRequests() const {
+                        int32_t requests = 0;
+                        for (auto request : mDisplayRequests) {
+                            requests |= static_cast<int32_t>(request);
+                        }
+                        return requests;
+                    }
+
+                    void addTypeChange(hwc2_layer_t layerId,
+                            HWC2::Composition type) {
+                        mTypeChanges.insert({layerId, type});
+                    }
+
+                    void clearTypeChanges() { mTypeChanges.clear(); }
+
+                    void addLayerRequest(hwc2_layer_t layerId,
+                            HWC2::LayerRequest request) {
+                        mLayerRequests.insert({layerId, request});
+                    }
+
+                private:
+                    std::unordered_map<hwc2_layer_t, HWC2::Composition>
+                            mTypeChanges;
+                    std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
+                            mLayerRequests;
+                    std::unordered_set<HWC2::DisplayRequest> mDisplayRequests;
+            };
+
+            std::shared_ptr<const Config>
+                    getConfig(hwc2_config_t configId) const;
+
+            void populateColorModes();
+            void initializeActiveConfig();
+
+            void reallocateHwc1Contents();
+            void assignHwc1LayerIds();
+
+            void updateTypeChanges(const struct hwc_layer_1& hwc1Layer,
+                    const Layer& layer);
+            void updateLayerRequests(const struct hwc_layer_1& hwc1Layer,
+                    const Layer& layer);
+
+            void prepareFramebufferTarget();
+
+            static std::atomic<hwc2_display_t> sNextId;
+            const hwc2_display_t mId;
+            HWC2On1Adapter& mDevice;
+
+            std::atomic<size_t> mDirtyCount;
+
+            // The state of this display should only be modified from
+            // SurfaceFlinger's main loop, with the exception of when dump is
+            // called. To prevent a bad state from crashing us during a dump
+            // call, all public calls into Display must acquire this mutex.
+            //
+            // It is recursive because we don't want to deadlock in validate
+            // (or present) when we call HWC2On1Adapter::prepareAllDisplays
+            // (or setAllDisplays), which calls back into Display functions
+            // which require locking.
+            mutable std::recursive_mutex mStateMutex;
+
+            bool mZIsDirty;
+            HWC1Contents mHwc1RequestedContents;
+            HWC1Contents mHwc1ReceivedContents;
+            DeferredFence mRetireFence;
+
+            // Will only be non-null after the layer has been validated but
+            // before it has been presented
+            std::unique_ptr<Changes> mChanges;
+
+            int32_t mHwc1Id;
+
+            std::vector<std::shared_ptr<Config>> mConfigs;
+            std::shared_ptr<const Config> mActiveConfig;
+            std::set<int32_t> mColorModes;
+            int32_t mActiveColorMode;
+            std::string mName;
+            HWC2::DisplayType mType;
+            HWC2::PowerMode mPowerMode;
+            HWC2::Vsync mVsyncEnabled;
+
+            FencedBuffer mClientTarget;
+            FencedBuffer mOutputBuffer;
+
+            bool mHasColorTransform;
+
+            std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
+            std::unordered_map<size_t, std::shared_ptr<Layer>> mHwc1LayerMap;
+    };
+
+    template <typename ...Args>
+    static int32_t callDisplayFunction(hwc2_device_t* device,
+            hwc2_display_t displayId, HWC2::Error (Display::*member)(Args...),
+            Args... args) {
+        auto display = getAdapter(device)->getDisplay(displayId);
+        if (!display) {
+            return static_cast<int32_t>(HWC2::Error::BadDisplay);
+        }
+        auto error = ((*display).*member)(std::forward<Args>(args)...);
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
+            Args... args) {
+        return HWC2On1Adapter::callDisplayFunction(device, displayId, memFunc,
+                std::forward<Args>(args)...);
+    }
+
+    static int32_t getDisplayAttributeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_config_t config,
+            int32_t intAttribute, int32_t* outValue) {
+        auto attribute = static_cast<HWC2::Attribute>(intAttribute);
+        return callDisplayFunction(device, display, &Display::getAttribute,
+                config, attribute, outValue);
+    }
+
+    static int32_t setColorTransformHook(hwc2_device_t* device,
+            hwc2_display_t display, const float* /*matrix*/,
+            int32_t /*android_color_transform_t*/ intHint) {
+        // We intentionally throw away the matrix, because if the hint is
+        // anything other than IDENTITY, we have to fall back to client
+        // composition anyway
+        auto hint = static_cast<android_color_transform_t>(intHint);
+        return callDisplayFunction(device, display, &Display::setColorTransform,
+                hint);
+    }
+
+    static int32_t setPowerModeHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t intMode) {
+        auto mode = static_cast<HWC2::PowerMode>(intMode);
+        return callDisplayFunction(device, display, &Display::setPowerMode,
+                mode);
+    }
+
+    static int32_t setVsyncEnabledHook(hwc2_device_t* device,
+            hwc2_display_t display, int32_t intEnabled) {
+        auto enabled = static_cast<HWC2::Vsync>(intEnabled);
+        return callDisplayFunction(device, display, &Display::setVsyncEnabled,
+                enabled);
+    }
+
+    // Layer functions
+
+    template <typename T>
+    class LatchedState {
+        public:
+            LatchedState(Layer& parent, T initialValue)
+              : mParent(parent),
+                mPendingValue(initialValue),
+                mValue(initialValue) {}
+
+            void setPending(T value) {
+                if (value == mPendingValue) {
+                    return;
+                }
+                if (mPendingValue == mValue) {
+                    mParent.incDirty();
+                } else if (value == mValue) {
+                    mParent.decDirty();
+                }
+                mPendingValue = value;
+            }
+
+            T getValue() const { return mValue; }
+            T getPendingValue() const { return mPendingValue; }
+
+            bool isDirty() const { return mPendingValue != mValue; }
+
+            void latch() {
+                if (isDirty()) {
+                    mValue = mPendingValue;
+                    mParent.decDirty();
+                }
+            }
+
+        private:
+            Layer& mParent;
+            T mPendingValue;
+            T mValue;
+    };
+
+    class Layer {
+        public:
+            Layer(Display& display);
+
+            bool operator==(const Layer& other) { return mId == other.mId; }
+            bool operator!=(const Layer& other) { return !(*this == other); }
+
+            hwc2_layer_t getId() const { return mId; }
+            Display& getDisplay() const { return mDisplay; }
+
+            void incDirty() { if (mDirtyCount++ == 0) mDisplay.incDirty(); }
+            void decDirty() { if (--mDirtyCount == 0) mDisplay.decDirty(); }
+            bool isDirty() const { return mDirtyCount > 0; }
+
+            // HWC2 Layer functions
+            HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
+            HWC2::Error setCursorPosition(int32_t x, int32_t y);
+            HWC2::Error setSurfaceDamage(hwc_region_t damage);
+
+            // HWC2 Layer state functions
+            HWC2::Error setBlendMode(HWC2::BlendMode mode);
+            HWC2::Error setColor(hwc_color_t color);
+            HWC2::Error setCompositionType(HWC2::Composition type);
+            HWC2::Error setDataspace(android_dataspace_t dataspace);
+            HWC2::Error setDisplayFrame(hwc_rect_t frame);
+            HWC2::Error setPlaneAlpha(float alpha);
+            HWC2::Error setSidebandStream(const native_handle_t* stream);
+            HWC2::Error setSourceCrop(hwc_frect_t crop);
+            HWC2::Error setTransform(HWC2::Transform transform);
+            HWC2::Error setVisibleRegion(hwc_region_t visible);
+            HWC2::Error setZ(uint32_t z);
+
+            HWC2::Composition getCompositionType() const {
+                return mCompositionType.getValue();
+            }
+            uint32_t getZ() const { return mZ; }
+
+            void addReleaseFence(int fenceFd);
+            const sp<Fence>& getReleaseFence() const;
+
+            void setHwc1Id(size_t id) { mHwc1Id = id; }
+            size_t getHwc1Id() const { return mHwc1Id; }
+
+            void applyState(struct hwc_layer_1& hwc1Layer, bool applyAllState);
+
+            std::string dump() const;
+
+        private:
+            void applyCommonState(struct hwc_layer_1& hwc1Layer,
+                    bool applyAllState);
+            void applySolidColorState(struct hwc_layer_1& hwc1Layer,
+                    bool applyAllState);
+            void applySidebandState(struct hwc_layer_1& hwc1Layer,
+                    bool applyAllState);
+            void applyBufferState(struct hwc_layer_1& hwc1Layer);
+            void applyCompositionType(struct hwc_layer_1& hwc1Layer,
+                    bool applyAllState);
+
+            static std::atomic<hwc2_layer_t> sNextId;
+            const hwc2_layer_t mId;
+            Display& mDisplay;
+            size_t mDirtyCount;
+
+            FencedBuffer mBuffer;
+            std::vector<hwc_rect_t> mSurfaceDamage;
+
+            LatchedState<HWC2::BlendMode> mBlendMode;
+            LatchedState<hwc_color_t> mColor;
+            LatchedState<HWC2::Composition> mCompositionType;
+            LatchedState<hwc_rect_t> mDisplayFrame;
+            LatchedState<float> mPlaneAlpha;
+            LatchedState<const native_handle_t*> mSidebandStream;
+            LatchedState<hwc_frect_t> mSourceCrop;
+            LatchedState<HWC2::Transform> mTransform;
+            LatchedState<std::vector<hwc_rect_t>> mVisibleRegion;
+            uint32_t mZ;
+
+            DeferredFence mReleaseFence;
+
+            size_t mHwc1Id;
+            bool mHasUnsupportedDataspace;
+            bool mHasUnsupportedPlaneAlpha;
+    };
+
+    template <typename ...Args>
+    static int32_t callLayerFunction(hwc2_device_t* device,
+            hwc2_display_t displayId, hwc2_layer_t layerId,
+            HWC2::Error (Layer::*member)(Args...), Args... args) {
+        auto result = getAdapter(device)->getLayer(displayId, layerId);
+        auto error = std::get<HWC2::Error>(result);
+        if (error == HWC2::Error::None) {
+            auto layer = std::get<Layer*>(result);
+            error = ((*layer).*member)(std::forward<Args>(args)...);
+        }
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
+            hwc2_layer_t layerId, Args... args) {
+        return HWC2On1Adapter::callLayerFunction(device, displayId, layerId,
+                memFunc, std::forward<Args>(args)...);
+    }
+
+    // Layer state functions
+
+    static int32_t setLayerBlendModeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intMode) {
+        auto mode = static_cast<HWC2::BlendMode>(intMode);
+        return callLayerFunction(device, display, layer,
+                &Layer::setBlendMode, mode);
+    }
+
+    static int32_t setLayerCompositionTypeHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intType) {
+        auto type = static_cast<HWC2::Composition>(intType);
+        return callLayerFunction(device, display, layer,
+                &Layer::setCompositionType, type);
+    }
+
+    static int32_t setLayerDataspaceHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intDataspace) {
+        auto dataspace = static_cast<android_dataspace_t>(intDataspace);
+        return callLayerFunction(device, display, layer, &Layer::setDataspace,
+                dataspace);
+    }
+
+    static int32_t setLayerTransformHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, int32_t intTransform) {
+        auto transform = static_cast<HWC2::Transform>(intTransform);
+        return callLayerFunction(device, display, layer, &Layer::setTransform,
+                transform);
+    }
+
+    static int32_t setLayerZOrderHook(hwc2_device_t* device,
+            hwc2_display_t display, hwc2_layer_t layer, uint32_t z) {
+        return callDisplayFunction(device, display, &Display::updateLayerZ,
+                layer, z);
+    }
+
+    // Adapter internals
+
+    void populateCapabilities();
+    Display* getDisplay(hwc2_display_t id);
+    std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
+            hwc2_layer_t layerId);
+    void populatePrimary();
+
+    bool prepareAllDisplays();
+    std::vector<struct hwc_display_contents_1*> mHwc1Contents;
+    HWC2::Error setAllDisplays();
+
+    void hwc1Invalidate();
+    void hwc1Vsync(int hwc1DisplayId, int64_t timestamp);
+    void hwc1Hotplug(int hwc1DisplayId, int connected);
+
+    // These are set in the constructor and before any asynchronous events are
+    // possible
+
+    struct hwc_composer_device_1* const mHwc1Device;
+    const uint8_t mHwc1MinorVersion;
+    bool mHwc1SupportsVirtualDisplays;
+
+    class Callbacks;
+    const std::unique_ptr<Callbacks> mHwc1Callbacks;
+
+    std::unordered_set<HWC2::Capability> mCapabilities;
+
+    // These are only accessed from the main SurfaceFlinger thread (not from
+    // callbacks or dump
+
+    std::map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;
+    std::shared_ptr<Display> mHwc1VirtualDisplay;
+
+    // These are potentially accessed from multiple threads, and are protected
+    // by this mutex. This needs to be recursive, since the HWC1 implementation
+    // can call back into the invalidate callback on the same thread that is
+    // calling prepare.
+    std::recursive_timed_mutex mStateMutex;
+
+    struct CallbackInfo {
+        hwc2_callback_data_t data;
+        hwc2_function_pointer_t pointer;
+    };
+    std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;
+    bool mHasPendingInvalidate;
+    std::vector<std::pair<int, int64_t>> mPendingVsyncs;
+    std::vector<std::pair<int, int>> mPendingHotplugs;
+
+    std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
+    std::unordered_map<int, hwc2_display_t> mHwc1DisplayMap;
+};
+
+} // namespace android
+
+#endif
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0859149..0bec0b8 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+
+#undef LOG_TAG
+#define LOG_TAG "HWComposer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <inttypes.h>
@@ -43,6 +47,8 @@
 #include <cutils/properties.h>
 
 #include "HWComposer.h"
+#include "HWC2On1Adapter.h"
+#include "HWC2.h"
 
 #include "../Layer.h"           // needed only for debugging
 #include "../SurfaceFlinger.h"
@@ -51,1103 +57,706 @@
 
 #define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
 
-static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
-    uint32_t hwcVersion = hwc->common.version;
-    return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
-}
-
-static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
-    uint32_t hwcVersion = hwc->common.version;
-    return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
-}
-
-static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
-        uint32_t version) {
-    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
-}
-
 // ---------------------------------------------------------------------------
 
-struct HWComposer::cb_context {
-    struct callbacks : public hwc_procs_t {
-        // these are here to facilitate the transition when adding
-        // new callbacks (an implementation can check for NULL before
-        // calling a new callback).
-        void (*zero[4])(void);
-    };
-    callbacks procs;
-    HWComposer* hwc;
-};
-
-// ---------------------------------------------------------------------------
-
-HWComposer::HWComposer(
-        const sp<SurfaceFlinger>& flinger,
-        EventHandler& handler)
+HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger)
     : mFlinger(flinger),
-      mFbDev(0), mHwc(0), mNumDisplays(1),
-      mCBContext(new cb_context),
-      mEventHandler(handler),
-      mDebugForceFakeVSync(false)
+      mAdapter(),
+      mHwcDevice(),
+      mDisplayData(2),
+      mFreeDisplaySlots(),
+      mHwcDisplaySlots(),
+      mCBContext(),
+      mEventHandler(nullptr),
+      mVSyncCounts(),
+      mRemainingHwcVirtualDisplays(0)
 {
-    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
-        mLists[i] = 0;
-    }
-
     for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
         mLastHwVSync[i] = 0;
         mVSyncCounts[i] = 0;
     }
 
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.no_hw_vsync", value, "0");
-    mDebugForceFakeVSync = atoi(value);
-
-    bool needVSyncThread = true;
-
-    // Note: some devices may insist that the FB HAL be opened before HWC.
-    int fberr = loadFbHalModule();
     loadHwcModule();
-
-    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        // close FB HAL if we don't needed it.
-        // FIXME: this is temporary until we're not forced to open FB HAL
-        // before HWC.
-        framebuffer_close(mFbDev);
-        mFbDev = NULL;
-    }
-
-    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
-    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-            && !mFbDev) {
-        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
-                strerror(-fberr));
-        abort();
-    }
-
-    // these display IDs are always reserved
-    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
-        mAllocatedDisplayIDs.markBit(i);
-    }
-
-    if (mHwc) {
-        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
-              (hwcApiVersion(mHwc) >> 24) & 0xff,
-              (hwcApiVersion(mHwc) >> 16) & 0xff);
-        if (mHwc->registerProcs) {
-            mCBContext->hwc = this;
-            mCBContext->procs.invalidate = &hook_invalidate;
-            mCBContext->procs.vsync = &hook_vsync;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-                mCBContext->procs.hotplug = &hook_hotplug;
-            else
-                mCBContext->procs.hotplug = NULL;
-            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
-            mHwc->registerProcs(mHwc, &mCBContext->procs);
-        }
-
-        // don't need a vsync thread if we have a hardware composer
-        needVSyncThread = false;
-        // always turn vsync off when we start
-        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
-
-        // the number of displays we actually have depends on the
-        // hw composer version
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-            // 1.3 adds support for virtual displays
-            mNumDisplays = MAX_HWC_DISPLAYS;
-        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // 1.1 adds support for multiple displays
-            mNumDisplays = NUM_BUILTIN_DISPLAYS;
-        } else {
-            mNumDisplays = 1;
-        }
-    }
-
-    if (mFbDev) {
-        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
-                "should only have fbdev if no hwc or hwc is 1.0");
-
-        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
-        disp.connected = true;
-        disp.format = mFbDev->format;
-        DisplayConfig config = DisplayConfig();
-        config.width = mFbDev->width;
-        config.height = mFbDev->height;
-        config.xdpi = mFbDev->xdpi;
-        config.ydpi = mFbDev->ydpi;
-        config.refresh = nsecs_t(1e9 / mFbDev->fps);
-        disp.configs.push_back(config);
-        disp.currentConfig = 0;
-    } else if (mHwc) {
-        // here we're guaranteed to have at least HWC 1.1
-        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
-            queryDisplayProperties(i);
-        }
-    }
-
-    if (needVSyncThread) {
-        // we don't have VSYNC support, we need to fake it
-        mVSyncThread = new VSyncThread(*this);
-    }
 }
 
-HWComposer::~HWComposer() {
-    if (mHwc) {
-        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+HWComposer::~HWComposer() {}
+
+void HWComposer::setEventHandler(EventHandler* handler)
+{
+    if (handler == nullptr) {
+        ALOGE("setEventHandler: Rejected attempt to clear handler");
+        return;
     }
-    if (mVSyncThread != NULL) {
-        mVSyncThread->requestExitAndWait();
+
+    bool wasNull = (mEventHandler == nullptr);
+    mEventHandler = handler;
+
+    if (wasNull) {
+        auto hotplugHook = std::bind(&HWComposer::hotplug, this,
+                std::placeholders::_1, std::placeholders::_2);
+        mHwcDevice->registerHotplugCallback(hotplugHook);
+        auto invalidateHook = std::bind(&HWComposer::invalidate, this,
+                std::placeholders::_1);
+        mHwcDevice->registerRefreshCallback(invalidateHook);
+        auto vsyncHook = std::bind(&HWComposer::vsync, this,
+                std::placeholders::_1, std::placeholders::_2);
+        mHwcDevice->registerVsyncCallback(vsyncHook);
     }
-    if (mHwc) {
-        hwc_close_1(mHwc);
-    }
-    if (mFbDev) {
-        framebuffer_close(mFbDev);
-    }
-    delete mCBContext;
 }
 
 // Load and prepare the hardware composer module.  Sets mHwc.
 void HWComposer::loadHwcModule()
 {
+    ALOGV("loadHwcModule");
+
     hw_module_t const* module;
 
     if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
-        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
-        return;
+        ALOGE("%s module not found, aborting", HWC_HARDWARE_MODULE_ID);
+        abort();
     }
 
-    int err = hwc_open_1(module, &mHwc);
-    if (err) {
-        ALOGE("%s device failed to initialize (%s)",
-              HWC_HARDWARE_COMPOSER, strerror(-err));
-        return;
+    hw_device_t* device = nullptr;
+    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
+    if (error != 0) {
+        ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
+        abort();
     }
 
-    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
-            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
-            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
-        ALOGE("%s device version %#x unsupported, will not be used",
-              HWC_HARDWARE_COMPOSER, mHwc->common.version);
-        hwc_close_1(mHwc);
-        mHwc = NULL;
-        return;
+    uint32_t majorVersion = (device->version >> 24) & 0xF;
+    if (majorVersion == 2) {
+        mHwcDevice = std::make_unique<HWC2::Device>(
+                reinterpret_cast<hwc2_device_t*>(device));
+    } else {
+        mAdapter = std::make_unique<HWC2On1Adapter>(
+                reinterpret_cast<hwc_composer_device_1_t*>(device));
+        uint8_t minorVersion = mAdapter->getHwc1MinorVersion();
+        if (minorVersion < 1) {
+            ALOGE("Cannot adapt to HWC version %d.%d",
+                    static_cast<int32_t>((minorVersion >> 8) & 0xF),
+                    static_cast<int32_t>(minorVersion & 0xF));
+            abort();
+        }
+        mHwcDevice = std::make_unique<HWC2::Device>(
+                static_cast<hwc2_device_t*>(mAdapter.get()));
+    }
+
+    mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
+}
+
+bool HWComposer::isValidDisplay(int32_t displayId) const {
+    return static_cast<size_t>(displayId) < mDisplayData.size() &&
+            mDisplayData[displayId].hwcDisplay;
+}
+
+void HWComposer::validateChange(HWC2::Composition from, HWC2::Composition to) {
+    bool valid = true;
+    switch (from) {
+        case HWC2::Composition::Client:
+            valid = false;
+            break;
+        case HWC2::Composition::Device:
+        case HWC2::Composition::SolidColor:
+            valid = (to == HWC2::Composition::Client);
+            break;
+        case HWC2::Composition::Cursor:
+        case HWC2::Composition::Sideband:
+            valid = (to == HWC2::Composition::Client ||
+                    to == HWC2::Composition::Device);
+            break;
+        default:
+            break;
+    }
+
+    if (!valid) {
+        ALOGE("Invalid layer type change: %s --> %s", to_string(from).c_str(),
+                to_string(to).c_str());
     }
 }
 
-// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
-int HWComposer::loadFbHalModule()
-{
-    hw_module_t const* module;
-
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err != 0) {
-        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
-        return err;
+void HWComposer::hotplug(const std::shared_ptr<HWC2::Display>& display,
+        HWC2::Connection connected) {
+    ALOGV("hotplug: %" PRIu64 ", %s", display->getId(),
+            to_string(connected).c_str());
+    int32_t disp = 0;
+    if (!mDisplayData[0].hwcDisplay) {
+        ALOGE_IF(connected != HWC2::Connection::Connected, "Assumed primary"
+                " display would be connected");
+        mDisplayData[0].hwcDisplay = display;
+        mHwcDisplaySlots[display->getId()] = 0;
+        disp = DisplayDevice::DISPLAY_PRIMARY;
+    } else {
+        // Disconnect is handled through HWComposer::disconnectDisplay via
+        // SurfaceFlinger's onHotplugReceived callback handling
+        if (connected == HWC2::Connection::Connected) {
+            mDisplayData[1].hwcDisplay = display;
+            mHwcDisplaySlots[display->getId()] = 1;
+        }
+        disp = DisplayDevice::DISPLAY_EXTERNAL;
     }
-
-    return framebuffer_open(module, &mFbDev);
+    mEventHandler->onHotplugReceived(disp,
+            connected == HWC2::Connection::Connected);
 }
 
-status_t HWComposer::initCheck() const {
-    return mHwc ? NO_ERROR : NO_INIT;
-}
-
-void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->invalidate();
-}
-
-void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
-        int64_t timestamp) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->vsync(disp, timestamp);
-}
-
-void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
-        int connected) {
-    cb_context* ctx = reinterpret_cast<cb_context*>(
-            const_cast<hwc_procs_t*>(procs));
-    ctx->hwc->hotplug(disp, connected);
-}
-
-void HWComposer::invalidate() {
+void HWComposer::invalidate(const std::shared_ptr<HWC2::Display>& /*display*/) {
     mFlinger->repaintEverything();
 }
 
-void HWComposer::vsync(int disp, int64_t timestamp) {
-    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
-        {
-            Mutex::Autolock _l(mLock);
-
-            // There have been reports of HWCs that signal several vsync events
-            // with the same timestamp when turning the display off and on. This
-            // is a bug in the HWC implementation, but filter the extra events
-            // out here so they don't cause havoc downstream.
-            if (timestamp == mLastHwVSync[disp]) {
-                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
-                        timestamp);
-                return;
-            }
-
-            mLastHwVSync[disp] = timestamp;
-        }
-
-        char tag[16];
-        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
-        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
-
-        mEventHandler.onVSyncReceived(disp, timestamp);
-    }
-}
-
-void HWComposer::hotplug(int disp, int connected) {
-    if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
-        ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
-                disp, connected);
+void HWComposer::vsync(const std::shared_ptr<HWC2::Display>& display,
+        int64_t timestamp) {
+    auto displayType = HWC2::DisplayType::Invalid;
+    auto error = display->getType(&displayType);
+    if (error != HWC2::Error::None) {
+        ALOGE("vsync: Failed to determine type of display %" PRIu64,
+                display->getId());
         return;
     }
-    queryDisplayProperties(disp);
-    // Do not teardown or recreate the primary display
-    if (disp != HWC_DISPLAY_PRIMARY) {
-        mEventHandler.onHotplugReceived(disp, bool(connected));
-    }
-}
 
-static float getDefaultDensity(uint32_t width, uint32_t height) {
-    // Default density is based on TVs: 1080p displays get XHIGH density,
-    // lower-resolution displays get TV density. Maybe eventually we'll need
-    // to update it for 4K displays, though hopefully those just report
-    // accurate DPI information to begin with. This is also used for virtual
-    // displays and even primary displays with older hwcomposers, so be
-    // careful about orientation.
-
-    uint32_t h = width < height ? width : height;
-    if (h >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
-    else           return ACONFIGURATION_DENSITY_TV;
-}
-
-static const uint32_t DISPLAY_ATTRIBUTES[] = {
-    HWC_DISPLAY_VSYNC_PERIOD,
-    HWC_DISPLAY_WIDTH,
-    HWC_DISPLAY_HEIGHT,
-    HWC_DISPLAY_DPI_X,
-    HWC_DISPLAY_DPI_Y,
-    HWC_DISPLAY_COLOR_TRANSFORM,
-    HWC_DISPLAY_NO_ATTRIBUTE,
-};
-#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
-
-static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
-    HWC_DISPLAY_VSYNC_PERIOD,
-    HWC_DISPLAY_WIDTH,
-    HWC_DISPLAY_HEIGHT,
-    HWC_DISPLAY_DPI_X,
-    HWC_DISPLAY_DPI_Y,
-    HWC_DISPLAY_NO_ATTRIBUTE,
-};
-
-status_t HWComposer::queryDisplayProperties(int disp) {
-
-    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-
-    // use zero as default value for unspecified attributes
-    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
-    memset(values, 0, sizeof(values));
-
-    const size_t MAX_NUM_CONFIGS = 128;
-    uint32_t configs[MAX_NUM_CONFIGS] = {0};
-    size_t numConfigs = MAX_NUM_CONFIGS;
-    status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
-    if (err != NO_ERROR) {
-        // this can happen if an unpluggable display is not connected
-        mDisplayData[disp].connected = false;
-        return err;
+    if (displayType == HWC2::DisplayType::Virtual) {
+        ALOGE("Virtual display %" PRIu64 " passed to vsync callback",
+                display->getId());
+        return;
     }
 
-    mDisplayData[disp].currentConfig = 0;
-    for (size_t c = 0; c < numConfigs; ++c) {
-        err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
-                DISPLAY_ATTRIBUTES, values);
-        // If this is a pre-1.5 HWC, it may not know about color transform, so
-        // try again with a smaller set of attributes
-        if (err != NO_ERROR) {
-            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
-                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
-        }
-        if (err != NO_ERROR) {
-            // we can't get this display's info. turn it off.
-            mDisplayData[disp].connected = false;
-            return err;
-        }
-
-        DisplayConfig config = DisplayConfig();
-        for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
-            switch (DISPLAY_ATTRIBUTES[i]) {
-                case HWC_DISPLAY_VSYNC_PERIOD:
-                    config.refresh = nsecs_t(values[i]);
-                    break;
-                case HWC_DISPLAY_WIDTH:
-                    config.width = values[i];
-                    break;
-                case HWC_DISPLAY_HEIGHT:
-                    config.height = values[i];
-                    break;
-                case HWC_DISPLAY_DPI_X:
-                    config.xdpi = values[i] / 1000.0f;
-                    break;
-                case HWC_DISPLAY_DPI_Y:
-                    config.ydpi = values[i] / 1000.0f;
-                    break;
-                case HWC_DISPLAY_COLOR_TRANSFORM:
-                    config.colorTransform = values[i];
-                    break;
-                default:
-                    ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
-                            i, DISPLAY_ATTRIBUTES[i]);
-                    break;
-            }
-        }
-
-        if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
-            float dpi = getDefaultDensity(config.width, config.height);
-            config.xdpi = dpi;
-            config.ydpi = dpi;
-        }
-
-        mDisplayData[disp].configs.push_back(config);
+    if (mHwcDisplaySlots.count(display->getId()) == 0) {
+        ALOGE("Unknown physical display %" PRIu64 " passed to vsync callback",
+                display->getId());
+        return;
     }
 
-    // FIXME: what should we set the format to?
-    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
-    mDisplayData[disp].connected = true;
-    return NO_ERROR;
-}
+    int32_t disp = mHwcDisplaySlots[display->getId()];
+    {
+        Mutex::Autolock _l(mLock);
 
-status_t HWComposer::setVirtualDisplayProperties(int32_t id,
-        uint32_t w, uint32_t h, uint32_t format) {
-    if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
-            !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
+        // There have been reports of HWCs that signal several vsync events
+        // with the same timestamp when turning the display off and on. This
+        // is a bug in the HWC implementation, but filter the extra events
+        // out here so they don't cause havoc downstream.
+        if (timestamp == mLastHwVSync[disp]) {
+            ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
+                    timestamp);
+            return;
+        }
+
+        mLastHwVSync[disp] = timestamp;
     }
-    size_t configId = mDisplayData[id].currentConfig;
-    mDisplayData[id].format = format;
-    DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
-    config.width = w;
-    config.height = h;
-    config.xdpi = config.ydpi = getDefaultDensity(w, h);
-    return NO_ERROR;
+
+    char tag[16];
+    snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
+    ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
+
+    mEventHandler->onVSyncReceived(disp, timestamp);
 }
 
-int32_t HWComposer::allocateDisplayId() {
-    if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
+status_t HWComposer::allocateVirtualDisplay(uint32_t width, uint32_t height,
+        int32_t *outId) {
+    if (mRemainingHwcVirtualDisplays == 0) {
+        ALOGE("allocateVirtualDisplay: No remaining virtual displays");
         return NO_MEMORY;
     }
-    int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
-    mAllocatedDisplayIDs.markBit(id);
-    mDisplayData[id].connected = true;
-    mDisplayData[id].configs.resize(1);
-    mDisplayData[id].currentConfig = 0;
-    return id;
-}
 
-status_t HWComposer::freeDisplayId(int32_t id) {
-    if (id < NUM_BUILTIN_DISPLAYS) {
-        // cannot free the reserved IDs
-        return BAD_VALUE;
+    std::shared_ptr<HWC2::Display> display;
+    auto error = mHwcDevice->createVirtualDisplay(width, height, &display);
+    if (error != HWC2::Error::None) {
+        ALOGE("allocateVirtualDisplay: Failed to create HWC virtual display");
+        return NO_MEMORY;
     }
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
+
+    size_t displaySlot = 0;
+    if (!mFreeDisplaySlots.empty()) {
+        displaySlot = *mFreeDisplaySlots.begin();
+        mFreeDisplaySlots.erase(displaySlot);
+    } else if (mDisplayData.size() < INT32_MAX) {
+        // Don't bother allocating a slot larger than we can return
+        displaySlot = mDisplayData.size();
+        mDisplayData.resize(displaySlot + 1);
+    } else {
+        ALOGE("allocateVirtualDisplay: Unable to allocate a display slot");
+        return NO_MEMORY;
     }
-    mAllocatedDisplayIDs.clearBit(id);
-    mDisplayData[id].connected = false;
+
+    mDisplayData[displaySlot].hwcDisplay = display;
+
+    --mRemainingHwcVirtualDisplays;
+    *outId = static_cast<int32_t>(displaySlot);
+
     return NO_ERROR;
 }
 
-nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
+std::shared_ptr<HWC2::Layer> HWComposer::createLayer(int32_t displayId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("Failed to create layer on invalid display %d", displayId);
+        return nullptr;
+    }
+    auto display = mDisplayData[displayId].hwcDisplay;
+    std::shared_ptr<HWC2::Layer> layer;
+    auto error = display->createLayer(&layer);
+    if (error != HWC2::Error::None) {
+        ALOGE("Failed to create layer on display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return nullptr;
+    }
+    return layer;
+}
+
+nsecs_t HWComposer::getRefreshTimestamp(int32_t disp) const {
     // this returns the last refresh timestamp.
     // if the last one is not available, we estimate it based on
     // the refresh period and whatever closest timestamp we have.
     Mutex::Autolock _l(mLock);
     nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    size_t configId = mDisplayData[disp].currentConfig;
-    return now - ((now - mLastHwVSync[disp]) %
-            mDisplayData[disp].configs[configId].refresh);
+    auto vsyncPeriod = getActiveConfig(disp)->getVsyncPeriod();
+    return now - ((now - mLastHwVSync[disp]) % vsyncPeriod);
 }
 
-sp<Fence> HWComposer::getDisplayFence(int disp) const {
-    return mDisplayData[disp].lastDisplayFence;
-}
-
-uint32_t HWComposer::getFormat(int disp) const {
-    if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
-        return HAL_PIXEL_FORMAT_RGBA_8888;
-    } else {
-        return mDisplayData[disp].format;
-    }
-}
-
-bool HWComposer::isConnected(int disp) const {
-    return mDisplayData[disp].connected;
-}
-
-uint32_t HWComposer::getWidth(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].width;
-}
-
-uint32_t HWComposer::getHeight(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].height;
-}
-
-float HWComposer::getDpiX(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].xdpi;
-}
-
-float HWComposer::getDpiY(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].ydpi;
-}
-
-nsecs_t HWComposer::getRefreshPeriod(int disp) const {
-    size_t currentConfig = mDisplayData[disp].currentConfig;
-    return mDisplayData[disp].configs[currentConfig].refresh;
-}
-
-const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
-    return mDisplayData[disp].configs;
-}
-
-size_t HWComposer::getCurrentConfig(int disp) const {
-    return mDisplayData[disp].currentConfig;
-}
-
-void HWComposer::eventControl(int disp, int event, int enabled) {
-    if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
-        ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
-              event, disp, enabled);
-        return;
-    }
-    if (event != EVENT_VSYNC) {
-        ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
-              event, disp, enabled);
-        return;
-    }
-    status_t err = NO_ERROR;
-    if (mHwc && !mDebugForceFakeVSync) {
-        // NOTE: we use our own internal lock here because we have to call
-        // into the HWC with the lock held, and we want to make sure
-        // that even if HWC blocks (which it shouldn't), it won't
-        // affect other threads.
-        Mutex::Autolock _l(mEventControlLock);
-        const int32_t eventBit = 1UL << event;
-        const int32_t newValue = enabled ? eventBit : 0;
-        const int32_t oldValue = mDisplayData[disp].events & eventBit;
-        if (newValue != oldValue) {
-            ATRACE_CALL();
-            err = mHwc->eventControl(mHwc, disp, event, enabled);
-            if (!err) {
-                int32_t& events(mDisplayData[disp].events);
-                events = (events & ~eventBit) | newValue;
-
-                char tag[16];
-                snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
-                ATRACE_INT(tag, enabled);
-            }
-        }
-        // error here should not happen -- not sure what we should
-        // do if it does.
-        ALOGE_IF(err, "eventControl(%d, %d) failed %s",
-                event, enabled, strerror(-err));
-    }
-
-    if (err == NO_ERROR && mVSyncThread != NULL) {
-        mVSyncThread->setEnabled(enabled);
-    }
-}
-
-status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-
-    if (mHwc) {
-        DisplayData& disp(mDisplayData[id]);
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // we need space for the HWC_FRAMEBUFFER_TARGET
-            numLayers++;
-        }
-        if (disp.capacity < numLayers || disp.list == NULL) {
-            size_t size = sizeof(hwc_display_contents_1_t)
-                    + numLayers * sizeof(hwc_layer_1_t);
-            free(disp.list);
-            disp.list = (hwc_display_contents_1_t*)malloc(size);
-            disp.capacity = numLayers;
-        }
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
-            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
-            const DisplayConfig& currentConfig =
-                    disp.configs[disp.currentConfig];
-            const hwc_rect_t r = { 0, 0,
-                    (int) currentConfig.width, (int) currentConfig.height };
-            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
-            disp.framebufferTarget->hints = 0;
-            disp.framebufferTarget->flags = 0;
-            disp.framebufferTarget->handle = disp.fbTargetHandle;
-            disp.framebufferTarget->transform = 0;
-            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                disp.framebufferTarget->sourceCropf.left = 0;
-                disp.framebufferTarget->sourceCropf.top = 0;
-                disp.framebufferTarget->sourceCropf.right =
-                        currentConfig.width;
-                disp.framebufferTarget->sourceCropf.bottom =
-                        currentConfig.height;
-            } else {
-                disp.framebufferTarget->sourceCrop = r;
-            }
-            disp.framebufferTarget->displayFrame = r;
-            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
-            disp.framebufferTarget->visibleRegionScreen.rects =
-                &disp.framebufferTarget->displayFrame;
-            disp.framebufferTarget->acquireFenceFd = -1;
-            disp.framebufferTarget->releaseFenceFd = -1;
-            disp.framebufferTarget->planeAlpha = 0xFF;
-        }
-        disp.list->retireFenceFd = -1;
-        disp.list->flags = HWC_GEOMETRY_CHANGED;
-        disp.list->numHwLayers = numLayers;
-    }
-    return NO_ERROR;
-}
-
-status_t HWComposer::setFramebufferTarget(int32_t id,
-        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return BAD_INDEX;
-    }
-    DisplayData& disp(mDisplayData[id]);
-    if (!disp.framebufferTarget) {
-        // this should never happen, but apparently eglCreateWindowSurface()
-        // triggers a Surface::queueBuffer()  on some
-        // devices (!?) -- log and ignore.
-        ALOGE("HWComposer: framebufferTarget is null");
-        return NO_ERROR;
-    }
-
-    int acquireFenceFd = -1;
-    if (acquireFence->isValid()) {
-        acquireFenceFd = acquireFence->dup();
-    }
-
-    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
-    disp.fbTargetHandle = buf->handle;
-    disp.framebufferTarget->handle = disp.fbTargetHandle;
-    disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
-    return NO_ERROR;
-}
-
-status_t HWComposer::prepare() {
-    Mutex::Autolock _l(mDisplayLock);
-    for (size_t i=0 ; i<mNumDisplays ; i++) {
-        DisplayData& disp(mDisplayData[i]);
-        if (disp.framebufferTarget) {
-            // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
-            // DO NOT reset the handle field to NULL, because it's possible
-            // that we have nothing to redraw (eg: eglSwapBuffers() not called)
-            // in which case, we should continue to use the same buffer.
-            LOG_FATAL_IF(disp.list == NULL);
-            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
-        }
-        if (!disp.connected && disp.list != NULL) {
-            ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
-                  i, disp.list->numHwLayers);
-        }
-        mLists[i] = disp.list;
-        if (mLists[i]) {
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                mLists[i]->outbuf = disp.outbufHandle;
-                mLists[i]->outbufAcquireFenceFd = -1;
-            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // garbage data to catch improper use
-                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
-                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
-            } else {
-                mLists[i]->dpy = EGL_NO_DISPLAY;
-                mLists[i]->sur = EGL_NO_SURFACE;
-            }
-        }
-    }
-
-    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
-    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
-
-    if (err == NO_ERROR) {
-        // here we're just making sure that "skip" layers are set
-        // to HWC_FRAMEBUFFER and we're also counting how many layers
-        // we have of each type.
-        //
-        // If there are no window layers, we treat the display has having FB
-        // composition, because SurfaceFlinger will use GLES to draw the
-        // wormhole region.
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            disp.hasFbComp = false;
-            disp.hasOvComp = false;
-            if (disp.list) {
-                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
-                    hwc_layer_1_t& l = disp.list->hwLayers[i];
-
-                    //ALOGD("prepare: %d, type=%d, handle=%p",
-                    //        i, l.compositionType, l.handle);
-
-                    if (l.flags & HWC_SKIP_LAYER) {
-                        l.compositionType = HWC_FRAMEBUFFER;
-                    }
-                    if (l.compositionType == HWC_FRAMEBUFFER) {
-                        disp.hasFbComp = true;
-                    }
-                    if (l.compositionType == HWC_OVERLAY) {
-                        disp.hasOvComp = true;
-                    }
-                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
-                        disp.hasOvComp = true;
-                    }
-                }
-                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
-                    disp.hasFbComp = true;
-                }
-            } else {
-                disp.hasFbComp = true;
-            }
-        }
-    }
-    return (status_t)err;
-}
-
-bool HWComposer::hasHwcComposition(int32_t id) const {
-    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+bool HWComposer::isConnected(int32_t disp) const {
+    if (!isValidDisplay(disp)) {
+        ALOGE("isConnected: Attempted to access invalid display %d", disp);
         return false;
-    return mDisplayData[id].hasOvComp;
+    }
+    return mDisplayData[disp].hwcDisplay->isConnected();
 }
 
-bool HWComposer::hasGlesComposition(int32_t id) const {
-    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return true;
-    return mDisplayData[id].hasFbComp;
-}
-
-sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
-        return Fence::NO_FENCE;
-
-    int fd = INVALID_OPERATION;
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        const DisplayData& disp(mDisplayData[id]);
-        if (disp.framebufferTarget) {
-            fd = disp.framebufferTarget->releaseFenceFd;
-            disp.framebufferTarget->acquireFenceFd = -1;
-            disp.framebufferTarget->releaseFenceFd = -1;
+std::vector<std::shared_ptr<const HWC2::Display::Config>>
+        HWComposer::getConfigs(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getConfigs: Attempted to access invalid display %d", displayId);
+        return {};
+    }
+    auto& displayData = mDisplayData[displayId];
+    auto configs = mDisplayData[displayId].hwcDisplay->getConfigs();
+    if (displayData.configMap.empty()) {
+        for (size_t i = 0; i < configs.size(); ++i) {
+            displayData.configMap[i] = configs[i];
         }
     }
-    return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
+    return configs;
 }
 
-status_t HWComposer::commit() {
-    int err = NO_ERROR;
-    if (mHwc) {
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-            // On version 1.0, the OpenGL ES target surface is communicated
-            // by the (dpy, sur) fields and we are guaranteed to have only
-            // a single display.
-            mLists[0]->dpy = eglGetCurrentDisplay();
-            mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
-        }
-
-        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            if (disp.outbufHandle) {
-                mLists[i]->outbuf = disp.outbufHandle;
-                mLists[i]->outbufAcquireFenceFd =
-                        disp.outbufAcquireFence->dup();
-            }
-        }
-
-        err = mHwc->set(mHwc, mNumDisplays, mLists);
-
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            DisplayData& disp(mDisplayData[i]);
-            disp.lastDisplayFence = disp.lastRetireFence;
-            disp.lastRetireFence = Fence::NO_FENCE;
-            if (disp.list) {
-                if (disp.list->retireFenceFd != -1) {
-                    disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
-                    disp.list->retireFenceFd = -1;
-                }
-                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
-            }
-        }
+std::shared_ptr<const HWC2::Display::Config>
+        HWComposer::getActiveConfig(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getActiveConfigs: Attempted to access invalid display %d",
+                displayId);
+        return nullptr;
     }
-    return (status_t)err;
+    std::shared_ptr<const HWC2::Display::Config> config;
+    auto error = mDisplayData[displayId].hwcDisplay->getActiveConfig(&config);
+    if (error == HWC2::Error::BadConfig) {
+        ALOGV("getActiveConfig: No config active, returning null");
+        return nullptr;
+    } else if (error != HWC2::Error::None) {
+        ALOGE("getActiveConfig failed for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return nullptr;
+    } else if (!config) {
+        ALOGE("getActiveConfig returned an unknown config for display %d",
+                displayId);
+        return nullptr;
+    }
+
+    return config;
 }
 
-status_t HWComposer::setPowerMode(int disp, int mode) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    if (mHwc) {
-        if (mode == HWC_POWER_MODE_OFF) {
-            eventControl(disp, HWC_EVENT_VSYNC, 0);
-        }
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-            return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
+void HWComposer::setVsyncEnabled(int32_t disp, HWC2::Vsync enabled) {
+    if (disp < 0 || disp >= HWC_DISPLAY_VIRTUAL) {
+        ALOGD("setVsyncEnabled: Ignoring for virtual display %d", disp);
+        return;
+    }
+
+    if (!isValidDisplay(disp)) {
+        ALOGE("setVsyncEnabled: Attempted to access invalid display %d", disp);
+        return;
+    }
+
+    // NOTE: we use our own internal lock here because we have to call
+    // into the HWC with the lock held, and we want to make sure
+    // that even if HWC blocks (which it shouldn't), it won't
+    // affect other threads.
+    Mutex::Autolock _l(mVsyncLock);
+    auto& displayData = mDisplayData[disp];
+    if (enabled != displayData.vsyncEnabled) {
+        ATRACE_CALL();
+        auto error = displayData.hwcDisplay->setVsyncEnabled(enabled);
+        if (error == HWC2::Error::None) {
+            displayData.vsyncEnabled = enabled;
+
+            char tag[16];
+            snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
+            ATRACE_INT(tag, enabled == HWC2::Vsync::Enable ? 1 : 0);
         } else {
-            return (status_t)mHwc->blank(mHwc, disp,
-                    mode == HWC_POWER_MODE_OFF ? 1 : 0);
+            ALOGE("setVsyncEnabled: Failed to set vsync to %s on %d/%" PRIu64
+                    ": %s (%d)", to_string(enabled).c_str(), disp,
+                    mDisplayData[disp].hwcDisplay->getId(),
+                    to_string(error).c_str(), static_cast<int32_t>(error));
         }
     }
-    return NO_ERROR;
 }
 
-status_t HWComposer::setActiveConfig(int disp, int mode) {
-    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
-    DisplayData& dd(mDisplayData[disp]);
-    dd.currentConfig = mode;
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-        return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
-    } else {
-        LOG_FATAL_IF(mode != 0);
-    }
-    return NO_ERROR;
-}
-
-void HWComposer::disconnectDisplay(int disp) {
-    LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
-    DisplayData& dd(mDisplayData[disp]);
-    free(dd.list);
-    dd.list = NULL;
-    dd.framebufferTarget = NULL;    // points into dd.list
-    dd.fbTargetHandle = NULL;
-    dd.outbufHandle = NULL;
-    dd.lastRetireFence = Fence::NO_FENCE;
-    dd.lastDisplayFence = Fence::NO_FENCE;
-    dd.outbufAcquireFence = Fence::NO_FENCE;
-    // clear all the previous configs and repopulate when a new
-    // device is added
-    dd.configs.clear();
-}
-
-int HWComposer::getVisualID() const {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
-        // is supported by the implementation. we can only be in this case
-        // if we have HWC 1.1
-        return HAL_PIXEL_FORMAT_RGBA_8888;
-        //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
-    } else {
-        return mFbDev->format;
-    }
-}
-
-bool HWComposer::supportsFramebufferTarget() const {
-    return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
-}
-
-int HWComposer::fbPost(int32_t id,
-        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-        return setFramebufferTarget(id, acquireFence, buffer);
-    } else {
-        acquireFence->waitForever("HWComposer::fbPost");
-        return mFbDev->post(mFbDev, buffer->handle);
-    }
-}
-
-int HWComposer::fbCompositionComplete() {
-    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
-        return NO_ERROR;
-
-    if (mFbDev->compositionComplete) {
-        return mFbDev->compositionComplete(mFbDev);
-    } else {
-        return INVALID_OPERATION;
-    }
-}
-
-void HWComposer::fbDump(String8& result) {
-    if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        mFbDev->dump(mFbDev, buffer, SIZE);
-        result.append(buffer);
-    }
-}
-
-status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
-        const sp<GraphicBuffer>& buf) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+status_t HWComposer::setClientTarget(int32_t displayId,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& target,
+        android_dataspace_t dataspace) {
+    if (!isValidDisplay(displayId)) {
         return BAD_INDEX;
-    if (id < VIRTUAL_DISPLAY_ID_BASE)
-        return INVALID_OPERATION;
+    }
 
-    DisplayData& disp(mDisplayData[id]);
-    disp.outbufHandle = buf->handle;
-    disp.outbufAcquireFence = acquireFence;
+    ALOGV("setClientTarget for display %d", displayId);
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    buffer_handle_t handle = nullptr;
+    if ((target != nullptr) && target->getNativeBuffer()) {
+        handle = target->getNativeBuffer()->handle;
+    }
+    auto error = hwcDisplay->setClientTarget(handle, acquireFence, dataspace);
+    if (error != HWC2::Error::None) {
+        ALOGE("Failed to set client target for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return BAD_VALUE;
+    }
+
     return NO_ERROR;
 }
 
-sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+status_t HWComposer::prepare(DisplayDevice& displayDevice) {
+    ATRACE_CALL();
+
+    Mutex::Autolock _l(mDisplayLock);
+    auto displayId = displayDevice.getHwcDisplayId();
+    if (!isValidDisplay(displayId)) {
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    auto& hwcDisplay = displayData.hwcDisplay;
+    if (!hwcDisplay->isConnected()) {
+        return NO_ERROR;
+    }
+
+    uint32_t numTypes = 0;
+    uint32_t numRequests = 0;
+    auto error = hwcDisplay->validate(&numTypes, &numRequests);
+    if (error != HWC2::Error::None && error != HWC2::Error::HasChanges) {
+        ALOGE("prepare: validate failed for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return BAD_INDEX;
+    }
+
+    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::Composition>
+        changedTypes;
+    changedTypes.reserve(numTypes);
+    error = hwcDisplay->getChangedCompositionTypes(&changedTypes);
+    if (error != HWC2::Error::None) {
+        ALOGE("prepare: getChangedCompositionTypes failed on display %d: "
+                "%s (%d)", displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return BAD_INDEX;
+    }
+
+
+    displayData.displayRequests = static_cast<HWC2::DisplayRequest>(0);
+    std::unordered_map<std::shared_ptr<HWC2::Layer>, HWC2::LayerRequest>
+        layerRequests;
+    layerRequests.reserve(numRequests);
+    error = hwcDisplay->getRequests(&displayData.displayRequests,
+            &layerRequests);
+    if (error != HWC2::Error::None) {
+        ALOGE("prepare: getRequests failed on display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return BAD_INDEX;
+    }
+
+    displayData.hasClientComposition = false;
+    displayData.hasDeviceComposition = false;
+    for (auto& layer : displayDevice.getVisibleLayersSortedByZ()) {
+        auto hwcLayer = layer->getHwcLayer(displayId);
+
+        if (changedTypes.count(hwcLayer) != 0) {
+            // We pass false so we only update our state and don't call back
+            // into the HWC device
+            validateChange(layer->getCompositionType(displayId),
+                    changedTypes[hwcLayer]);
+            layer->setCompositionType(displayId, changedTypes[hwcLayer], false);
+        }
+
+        switch (layer->getCompositionType(displayId)) {
+            case HWC2::Composition::Client:
+                displayData.hasClientComposition = true;
+                break;
+            case HWC2::Composition::Device:
+            case HWC2::Composition::SolidColor:
+            case HWC2::Composition::Cursor:
+            case HWC2::Composition::Sideband:
+                displayData.hasDeviceComposition = true;
+                break;
+            default:
+                break;
+        }
+
+        if (layerRequests.count(hwcLayer) != 0 &&
+                layerRequests[hwcLayer] ==
+                        HWC2::LayerRequest::ClearClientTarget) {
+            layer->setClearClientTarget(displayId, true);
+        } else {
+            if (layerRequests.count(hwcLayer) != 0) {
+                ALOGE("prepare: Unknown layer request: %s",
+                        to_string(layerRequests[hwcLayer]).c_str());
+            }
+            layer->setClearClientTarget(displayId, false);
+        }
+    }
+
+    error = hwcDisplay->acceptChanges();
+    if (error != HWC2::Error::None) {
+        ALOGE("prepare: acceptChanges failed: %s", to_string(error).c_str());
+        return BAD_INDEX;
+    }
+
+    return NO_ERROR;
+}
+
+bool HWComposer::hasDeviceComposition(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("hasDeviceComposition: Invalid display %d", displayId);
+        return false;
+    }
+    return mDisplayData[displayId].hasDeviceComposition;
+}
+
+bool HWComposer::hasClientComposition(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("hasClientComposition: Invalid display %d", displayId);
+        return true;
+    }
+    return mDisplayData[displayId].hasClientComposition;
+}
+
+sp<Fence> HWComposer::getRetireFence(int32_t displayId) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getRetireFence failed for invalid display %d", displayId);
         return Fence::NO_FENCE;
-    return mDisplayData[id].lastRetireFence;
+    }
+    return mDisplayData[displayId].lastRetireFence;
 }
 
-status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
-{
-    if (mHwc->setCursorPositionAsync) {
-        return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
+sp<Fence> HWComposer::getLayerReleaseFence(int32_t displayId,
+        const std::shared_ptr<HWC2::Layer>& layer) const {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getLayerReleaseFence: Invalid display");
+        return Fence::NO_FENCE;
     }
-    else {
-        return NO_ERROR;
+    auto displayFences = mDisplayData[displayId].releaseFences;
+    if (displayFences.count(layer) == 0) {
+        ALOGV("getLayerReleaseFence: Release fence not found");
+        return Fence::NO_FENCE;
     }
+    return displayFences[layer];
 }
 
-/*
- * Helper template to implement a concrete HWCLayer
- * This holds the pointer to the concrete hwc layer type
- * and implements the "iterable" side of HWCLayer.
- */
-template<typename CONCRETE, typename HWCTYPE>
-class Iterable : public HWComposer::HWCLayer {
-protected:
-    HWCTYPE* const mLayerList;
-    HWCTYPE* mCurrentLayer;
-    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
-    inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
-    inline HWCTYPE* getLayer() { return mCurrentLayer; }
-    virtual ~Iterable() { }
-private:
-    // returns a copy of ourselves
-    virtual HWComposer::HWCLayer* dup() {
-        return new CONCRETE( static_cast<const CONCRETE&>(*this) );
-    }
-    virtual status_t setLayer(size_t index) {
-        mCurrentLayer = &mLayerList[index];
-        return NO_ERROR;
-    }
-};
+status_t HWComposer::commit(int32_t displayId) {
+    ATRACE_CALL();
 
-/*
- * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
- * This implements the HWCLayer side of HWCIterableLayer.
- */
-class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
-    struct hwc_composer_device_1* mHwc;
-public:
-    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer)
-        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc) { }
+    if (!isValidDisplay(displayId)) {
+        return BAD_INDEX;
+    }
 
-    virtual int32_t getCompositionType() const {
-        return getLayer()->compositionType;
+    auto& displayData = mDisplayData[displayId];
+    auto& hwcDisplay = displayData.hwcDisplay;
+    auto error = hwcDisplay->present(&displayData.lastRetireFence);
+    if (error != HWC2::Error::None) {
+        ALOGE("commit: present failed for display %d: %s (%d)", displayId,
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
     }
-    virtual uint32_t getHints() const {
-        return getLayer()->hints;
-    }
-    virtual sp<Fence> getAndResetReleaseFence() {
-        int fd = getLayer()->releaseFenceFd;
-        getLayer()->releaseFenceFd = -1;
-        return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
-    }
-    virtual void setAcquireFenceFd(int fenceFd) {
-        getLayer()->acquireFenceFd = fenceFd;
-    }
-    virtual void setPerFrameDefaultState() {
-        //getLayer()->compositionType = HWC_FRAMEBUFFER;
-    }
-    virtual void setPlaneAlpha(uint8_t alpha) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
-            getLayer()->planeAlpha = alpha;
-        } else {
-            if (alpha < 0xFF) {
-                getLayer()->flags |= HWC_SKIP_LAYER;
-            }
-        }
-    }
-    virtual void setDefaultState() {
-        hwc_layer_1_t* const l = getLayer();
-        l->compositionType = HWC_FRAMEBUFFER;
-        l->hints = 0;
-        l->flags = HWC_SKIP_LAYER;
-        l->handle = 0;
-        l->transform = 0;
-        l->blending = HWC_BLENDING_NONE;
-        l->visibleRegionScreen.numRects = 0;
-        l->visibleRegionScreen.rects = NULL;
-        l->acquireFenceFd = -1;
-        l->releaseFenceFd = -1;
-        l->planeAlpha = 0xFF;
-    }
-    virtual void setSkip(bool skip) {
-        if (skip) {
-            getLayer()->flags |= HWC_SKIP_LAYER;
-        } else {
-            getLayer()->flags &= ~HWC_SKIP_LAYER;
-        }
-    }
-    virtual void setIsCursorLayerHint(bool isCursor) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
-            if (isCursor) {
-                getLayer()->flags |= HWC_IS_CURSOR_LAYER;
-            }
-            else {
-                getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
-            }
-        }
-    }
-    virtual void setBlending(uint32_t blending) {
-        getLayer()->blending = blending;
-    }
-    virtual void setTransform(uint32_t transform) {
-        getLayer()->transform = transform;
-    }
-    virtual void setFrame(const Rect& frame) {
-        getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
-    }
-    virtual void setCrop(const FloatRect& crop) {
-        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-            getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
-        } else {
-            /*
-             * Since h/w composer didn't support a flot crop rect before version 1.3,
-             * using integer coordinates instead produces a different output from the GL code in
-             * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
-             * window size ratio is large and a window crop is defined
-             * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
-             */
-            hwc_rect_t& r = getLayer()->sourceCrop;
-            r.left  = int(ceilf(crop.left));
-            r.top   = int(ceilf(crop.top));
-            r.right = int(floorf(crop.right));
-            r.bottom= int(floorf(crop.bottom));
-        }
-    }
-    virtual void setVisibleRegionScreen(const Region& reg) {
-        // Region::getSharedBuffer creates a reference to the underlying
-        // SharedBuffer of this Region, this reference is freed
-        // in onDisplayed()
-        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
-        SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects);
-        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
-    }
-    virtual void setSurfaceDamage(const Region& reg) {
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
-            return;
-        }
-        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
-        // We encode default full-screen damage as INVALID_RECT upstream, but as
-        // 0 rects for HWComposer
-        if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
-            surfaceDamage.numRects = 0;
-            surfaceDamage.rects = NULL;
-            return;
-        }
-        SharedBuffer const* sb = reg.getSharedBuffer(&surfaceDamage.numRects);
-        surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(sb->data());
-    }
-    virtual void setSidebandStream(const sp<NativeHandle>& stream) {
-        ALOG_ASSERT(stream->handle() != NULL);
-        getLayer()->compositionType = HWC_SIDEBAND;
-        getLayer()->sidebandStream = stream->handle();
-    }
-    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
-        if (buffer == 0 || buffer->handle == 0) {
-            getLayer()->compositionType = HWC_FRAMEBUFFER;
-            getLayer()->flags |= HWC_SKIP_LAYER;
-            getLayer()->handle = 0;
-        } else {
-            if (getLayer()->compositionType == HWC_SIDEBAND) {
-                // If this was a sideband layer but the stream was removed, reset
-                // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
-                getLayer()->compositionType = HWC_FRAMEBUFFER;
-            }
-            getLayer()->handle = buffer->handle;
-        }
-    }
-    virtual void onDisplayed() {
-        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
-        SharedBuffer const* sb = SharedBuffer::bufferFromData(visibleRegion.rects);
-        if (sb) {
-            sb->release();
-            // not technically needed but safer
-            visibleRegion.numRects = 0;
-            visibleRegion.rects = NULL;
-        }
 
-        getLayer()->acquireFenceFd = -1;
-
-        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
-            return;
-        }
-
-        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
-        sb = SharedBuffer::bufferFromData(surfaceDamage.rects);
-        if (sb) {
-            sb->release();
-            surfaceDamage.numRects = 0;
-            surfaceDamage.rects = NULL;
-        }
+    std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>> releaseFences;
+    error = hwcDisplay->getReleaseFences(&releaseFences);
+    if (error != HWC2::Error::None) {
+        ALOGE("commit: Failed to get release fences for display %d: %s (%d)",
+                displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
     }
-};
 
-/*
- * returns an iterator initialized at a given index in the layer list
- */
-HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
-    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
-        return LayerListIterator();
-    }
-    const DisplayData& disp(mDisplayData[id]);
-    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
-        return LayerListIterator();
-    }
-    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers), index);
+    displayData.releaseFences = std::move(releaseFences);
+
+    return NO_ERROR;
 }
 
-/*
- * returns an iterator on the beginning of the layer list
- */
-HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
-    return getLayerIterator(id, 0);
-}
+status_t HWComposer::setPowerMode(int32_t displayId, int32_t intMode) {
+    ALOGV("setPowerMode(%d, %d)", displayId, intMode);
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setPowerMode: Bad display");
+        return BAD_INDEX;
+    }
+    if (displayId >= VIRTUAL_DISPLAY_ID_BASE) {
+        ALOGE("setPowerMode: Virtual display %d passed in, returning",
+                displayId);
+        return BAD_INDEX;
+    }
 
-/*
- * returns an iterator on the end of the layer list
- */
-HWComposer::LayerListIterator HWComposer::end(int32_t id) {
-    size_t numLayers = 0;
-    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
-        const DisplayData& disp(mDisplayData[id]);
-        if (mHwc && disp.list) {
-            numLayers = disp.list->numHwLayers;
-            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
-                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
-                // which we ignore when iterating through the layer list.
-                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
-                if (numLayers) {
-                    numLayers--;
+    auto mode = static_cast<HWC2::PowerMode>(intMode);
+    if (mode == HWC2::PowerMode::Off) {
+        setVsyncEnabled(displayId, HWC2::Vsync::Disable);
+    }
+
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    switch (mode) {
+        case HWC2::PowerMode::Off:
+        case HWC2::PowerMode::On:
+            ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
+            {
+                auto error = hwcDisplay->setPowerMode(mode);
+                if (error != HWC2::Error::None) {
+                    ALOGE("setPowerMode: Unable to set power mode %s for "
+                            "display %d: %s (%d)", to_string(mode).c_str(),
+                            displayId, to_string(error).c_str(),
+                            static_cast<int32_t>(error));
                 }
             }
-        }
+            break;
+        case HWC2::PowerMode::Doze:
+        case HWC2::PowerMode::DozeSuspend:
+            ALOGV("setPowerMode: Calling HWC %s", to_string(mode).c_str());
+            {
+                bool supportsDoze = false;
+                auto error = hwcDisplay->supportsDoze(&supportsDoze);
+                if (error != HWC2::Error::None) {
+                    ALOGE("setPowerMode: Unable to query doze support for "
+                            "display %d: %s (%d)", displayId,
+                            to_string(error).c_str(),
+                            static_cast<int32_t>(error));
+                }
+                if (!supportsDoze) {
+                    mode = HWC2::PowerMode::On;
+                }
+
+                error = hwcDisplay->setPowerMode(mode);
+                if (error != HWC2::Error::None) {
+                    ALOGE("setPowerMode: Unable to set power mode %s for "
+                            "display %d: %s (%d)", to_string(mode).c_str(),
+                            displayId, to_string(error).c_str(),
+                            static_cast<int32_t>(error));
+                }
+            }
+            break;
+        default:
+            ALOGV("setPowerMode: Not calling HWC");
+            break;
     }
-    return getLayerIterator(id, numLayers);
+
+    return NO_ERROR;
+}
+
+status_t HWComposer::setActiveConfig(int32_t displayId, size_t configId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setActiveConfig: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& displayData = mDisplayData[displayId];
+    if (displayData.configMap.count(configId) == 0) {
+        ALOGE("setActiveConfig: Invalid config %zd", configId);
+        return BAD_INDEX;
+    }
+
+    auto error = displayData.hwcDisplay->setActiveConfig(
+            displayData.configMap[configId]);
+    if (error != HWC2::Error::None) {
+        ALOGE("setActiveConfig: Failed to set config %zu on display %d: "
+                "%s (%d)", configId, displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
+void HWComposer::disconnectDisplay(int displayId) {
+    LOG_ALWAYS_FATAL_IF(displayId < 0);
+    auto& displayData = mDisplayData[displayId];
+
+    auto displayType = HWC2::DisplayType::Invalid;
+    auto error = displayData.hwcDisplay->getType(&displayType);
+    if (error != HWC2::Error::None) {
+        ALOGE("disconnectDisplay: Failed to determine type of display %d",
+                displayId);
+        return;
+    }
+
+    // If this was a virtual display, add its slot back for reuse by future
+    // virtual displays
+    if (displayType == HWC2::DisplayType::Virtual) {
+        mFreeDisplaySlots.insert(displayId);
+        ++mRemainingHwcVirtualDisplays;
+    }
+
+    auto hwcId = displayData.hwcDisplay->getId();
+    mHwcDisplaySlots.erase(hwcId);
+    displayData.reset();
+}
+
+status_t HWComposer::setOutputBuffer(int32_t displayId,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("setOutputBuffer: Display %d is not valid", displayId);
+        return BAD_INDEX;
+    }
+
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    auto displayType = HWC2::DisplayType::Invalid;
+    auto error = hwcDisplay->getType(&displayType);
+    if (error != HWC2::Error::None) {
+        ALOGE("setOutputBuffer: Failed to determine type of display %d",
+                displayId);
+        return NAME_NOT_FOUND;
+    }
+
+    if (displayType != HWC2::DisplayType::Virtual) {
+        ALOGE("setOutputBuffer: Display %d is not virtual", displayId);
+        return INVALID_OPERATION;
+    }
+
+    error = hwcDisplay->setOutputBuffer(buffer, acquireFence);
+    if (error != HWC2::Error::None) {
+        ALOGE("setOutputBuffer: Failed to set buffer on display %d: %s (%d)",
+                displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return UNKNOWN_ERROR;
+    }
+
+    return NO_ERROR;
+}
+
+void HWComposer::clearReleaseFences(int32_t displayId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("clearReleaseFences: Display %d is not valid", displayId);
+        return;
+    }
+    mDisplayData[displayId].releaseFences.clear();
+}
+
+std::unique_ptr<HdrCapabilities> HWComposer::getHdrCapabilities(
+        int32_t displayId) {
+    if (!isValidDisplay(displayId)) {
+        ALOGE("getHdrCapabilities: Display %d is not valid", displayId);
+        return nullptr;
+    }
+
+    auto& hwcDisplay = mDisplayData[displayId].hwcDisplay;
+    std::unique_ptr<HdrCapabilities> capabilities;
+    auto error = hwcDisplay->getHdrCapabilities(&capabilities);
+    if (error != HWC2::Error::None) {
+        ALOGE("getOutputCapabilities: Failed to get capabilities on display %d:"
+                " %s (%d)", displayId, to_string(error).c_str(),
+                static_cast<int32_t>(error));
+        return nullptr;
+    }
+
+    return capabilities;
 }
 
 // Converts a PixelFormat to a human-readable string.  Max 11 chars.
 // (Could use a table of prefab String8 objects.)
+/*
 static String8 getFormatStr(PixelFormat format) {
     switch (format) {
     case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
@@ -1163,174 +772,34 @@
         return result;
     }
 }
+*/
 
 void HWComposer::dump(String8& result) const {
-    Mutex::Autolock _l(mDisplayLock);
-    if (mHwc) {
-        result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
-        result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
-        for (size_t i=0 ; i<mNumDisplays ; i++) {
-            const DisplayData& disp(mDisplayData[i]);
-            if (!disp.connected)
-                continue;
-
-            const Vector< sp<Layer> >& visibleLayersSortedByZ =
-                    mFlinger->getLayerSortedByZForHwcDisplay(i);
-
-
-            result.appendFormat("  Display[%zd] configurations (* current):\n", i);
-            for (size_t c = 0; c < disp.configs.size(); ++c) {
-                const DisplayConfig& config(disp.configs[c]);
-                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
-                        ", refresh=%" PRId64 ", colorTransform=%d\n",
-                        c == disp.currentConfig ? "* " : "", c,
-                        config.width, config.height, config.xdpi, config.ydpi,
-                        config.refresh, config.colorTransform);
-            }
-
-            if (disp.list) {
-                result.appendFormat(
-                        "  numHwLayers=%zu, flags=%08x\n",
-                        disp.list->numHwLayers, disp.list->flags);
-
-                result.append(
-                        "    type   |  handle  | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name \n"
-                        "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
-                //      " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
-                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
-                    const hwc_layer_1_t&l = disp.list->hwLayers[i];
-                    int32_t format = -1;
-                    String8 name("unknown");
-
-                    if (i < visibleLayersSortedByZ.size()) {
-                        const sp<Layer>& layer(visibleLayersSortedByZ[i]);
-                        const sp<GraphicBuffer>& buffer(
-                                layer->getActiveBuffer());
-                        if (buffer != NULL) {
-                            format = buffer->getPixelFormat();
-                        }
-                        name = layer->getName();
-                    }
-
-                    int type = l.compositionType;
-                    if (type == HWC_FRAMEBUFFER_TARGET) {
-                        name = "HWC_FRAMEBUFFER_TARGET";
-                        format = disp.format;
-                    }
-
-                    static char const* compositionTypeName[] = {
-                            "GLES",
-                            "HWC",
-                            "BKGND",
-                            "FB TARGET",
-                            "SIDEBAND",
-                            "HWC_CURSOR",
-                            "UNKNOWN"};
-                    if (type >= NELEM(compositionTypeName))
-                        type = NELEM(compositionTypeName) - 1;
-
-                    String8 formatStr = getFormatStr(format);
-                    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
-                        result.appendFormat(
-                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
-                                        compositionTypeName[type],
-                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
-                                        l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
-                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                        name.string());
-                    } else {
-                        result.appendFormat(
-                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
-                                        compositionTypeName[type],
-                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
-                                        l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
-                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
-                                        name.string());
-                    }
-                }
-            }
-        }
-    }
-
-    if (mHwc && mHwc->dump) {
-        const size_t SIZE = 4096;
-        char buffer[SIZE];
-        mHwc->dump(mHwc, buffer, SIZE);
-        result.append(buffer);
-    }
+    // TODO: In order to provide a dump equivalent to HWC1, we need to shadow
+    // all the state going into the layers. This is probably better done in
+    // Layer itself, but it's going to take a bit of work to get there.
+    result.append(mHwcDevice->dump().c_str());
 }
 
 // ---------------------------------------------------------------------------
 
-HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
-    : mHwc(hwc), mEnabled(false),
-      mNextFakeVSync(0),
-      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
-{
-}
-
-void HWComposer::VSyncThread::setEnabled(bool enabled) {
-    Mutex::Autolock _l(mLock);
-    if (mEnabled != enabled) {
-        mEnabled = enabled;
-        mCondition.signal();
-    }
-}
-
-void HWComposer::VSyncThread::onFirstRef() {
-    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
-}
-
-bool HWComposer::VSyncThread::threadLoop() {
-    { // scope for lock
-        Mutex::Autolock _l(mLock);
-        while (!mEnabled) {
-            mCondition.wait(mLock);
-        }
-    }
-
-    const nsecs_t period = mRefreshPeriod;
-    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
-    nsecs_t next_vsync = mNextFakeVSync;
-    nsecs_t sleep = next_vsync - now;
-    if (sleep < 0) {
-        // we missed, find where the next vsync should be
-        sleep = (period - ((now - next_vsync) % period));
-        next_vsync = now + sleep;
-    }
-    mNextFakeVSync = next_vsync + period;
-
-    struct timespec spec;
-    spec.tv_sec  = next_vsync / 1000000000;
-    spec.tv_nsec = next_vsync % 1000000000;
-
-    int err;
-    do {
-        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
-    } while (err<0 && errno == EINTR);
-
-    if (err == 0) {
-        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
-    }
-
-    return true;
-}
-
 HWComposer::DisplayData::DisplayData()
-:   configs(),
-    currentConfig(0),
-    format(HAL_PIXEL_FORMAT_RGBA_8888),
-    connected(false),
-    hasFbComp(false), hasOvComp(false),
-    capacity(0), list(NULL),
-    framebufferTarget(NULL), fbTargetHandle(0),
-    lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
-    outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
-    events(0)
-{}
+  : hasClientComposition(false),
+    hasDeviceComposition(false),
+    hwcDisplay(),
+    lastRetireFence(Fence::NO_FENCE),
+    outbufHandle(nullptr),
+    outbufAcquireFence(Fence::NO_FENCE),
+    vsyncEnabled(HWC2::Vsync::Disable) {
+    ALOGV("Created new DisplayData");
+}
 
 HWComposer::DisplayData::~DisplayData() {
-    free(list);
+}
+
+void HWComposer::DisplayData::reset() {
+    ALOGV("DisplayData reset");
+    *this = DisplayData();
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 5e0b3d8..d407877 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -14,14 +14,18 @@
  * limitations under the License.
  */
 
+#ifndef USE_HWC2
+#include "HWComposer_hwc1.h"
+#else
+
 #ifndef ANDROID_SF_HWCOMPOSER_H
 #define ANDROID_SF_HWCOMPOSER_H
 
+#include "HWC2.h"
+
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <hardware/hwcomposer_defs.h>
-
 #include <ui/Fence.h>
 
 #include <utils/BitSet.h>
@@ -32,22 +36,29 @@
 #include <utils/Timers.h>
 #include <utils/Vector.h>
 
+#include <memory>
+#include <set>
+#include <vector>
+
 extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
                            const struct timespec *request,
                            struct timespec *remain);
 
-struct hwc_composer_device_1;
-struct hwc_display_contents_1;
-struct hwc_layer_1;
-struct hwc_procs;
 struct framebuffer_device_t;
 
+namespace HWC2 {
+    class Device;
+    class Display;
+}
+
 namespace android {
 // ---------------------------------------------------------------------------
 
+class DisplayDevice;
 class Fence;
 class FloatRect;
 class GraphicBuffer;
+class HWC2On1Adapter;
 class NativeHandle;
 class Region;
 class String8;
@@ -58,198 +69,73 @@
 public:
     class EventHandler {
         friend class HWComposer;
-        virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0;
-        virtual void onHotplugReceived(int disp, bool connected) = 0;
+        virtual void onVSyncReceived(int32_t disp, nsecs_t timestamp) = 0;
+        virtual void onHotplugReceived(int32_t disp, bool connected) = 0;
     protected:
         virtual ~EventHandler() {}
     };
 
-    enum {
-        NUM_BUILTIN_DISPLAYS = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
-        MAX_HWC_DISPLAYS = HWC_NUM_DISPLAY_TYPES,
-        VIRTUAL_DISPLAY_ID_BASE = HWC_DISPLAY_VIRTUAL,
-    };
-
-    HWComposer(
-            const sp<SurfaceFlinger>& flinger,
-            EventHandler& handler);
+    HWComposer(const sp<SurfaceFlinger>& flinger);
 
     ~HWComposer();
 
-    status_t initCheck() const;
+    void setEventHandler(EventHandler* handler);
 
-    // Returns a display ID starting at VIRTUAL_DISPLAY_ID_BASE, this ID is to
-    // be used with createWorkList (and all other methods requiring an ID
-    // below).
-    // IDs below NUM_BUILTIN_DISPLAYS are pre-defined and therefore are
-    // always valid.
-    // Returns -1 if an ID cannot be allocated
-    int32_t allocateDisplayId();
+    // Attempts to allocate a virtual display. If the virtual display is created
+    // on the HWC device, outId will contain its HWC ID.
+    status_t allocateVirtualDisplay(uint32_t width, uint32_t height,
+            int32_t* outId);
 
-    // Recycles the given virtual display ID and frees the associated worklist.
-    // IDs below NUM_BUILTIN_DISPLAYS are not recycled.
-    status_t freeDisplayId(int32_t id);
-
+    // Attempts to create a new layer on this display
+    std::shared_ptr<HWC2::Layer> createLayer(int32_t displayId);
 
     // Asks the HAL what it can do
-    status_t prepare();
+    status_t prepare(DisplayDevice& displayDevice);
 
-    // commits the list
-    status_t commit();
+    status_t setClientTarget(int32_t displayId, const sp<Fence>& acquireFence,
+            const sp<GraphicBuffer>& target, android_dataspace_t dataspace);
+
+    // Finalize the layers and present them
+    status_t commit(int32_t displayId);
 
     // set power mode
-    status_t setPowerMode(int disp, int mode);
+    status_t setPowerMode(int32_t displayId, int mode);
 
     // set active config
-    status_t setActiveConfig(int disp, int mode);
+    status_t setActiveConfig(int32_t displayId, size_t configId);
 
     // reset state when an external, non-virtual display is disconnected
-    void disconnectDisplay(int disp);
-
-    // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
-    status_t createWorkList(int32_t id, size_t numLayers);
-
-    bool supportsFramebufferTarget() const;
+    void disconnectDisplay(int32_t displayId);
 
     // does this display have layers handled by HWC
-    bool hasHwcComposition(int32_t id) const;
+    bool hasDeviceComposition(int32_t displayId) const;
 
     // does this display have layers handled by GLES
-    bool hasGlesComposition(int32_t id) const;
+    bool hasClientComposition(int32_t displayId) const;
 
-    // get the releaseFence file descriptor for a display's framebuffer layer.
-    // the release fence is only valid after commit()
-    sp<Fence> getAndResetReleaseFence(int32_t id);
+    // get the retire fence for the previous frame (i.e., corresponding to the
+    // last call to presentDisplay
+    sp<Fence> getRetireFence(int32_t displayId) const;
 
-    // needed forward declarations
-    class LayerListIterator;
-
-    // return the visual id to be used to find a suitable EGLConfig for
-    // *ALL* displays.
-    int getVisualID() const;
-
-    // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
-    int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
-    int fbCompositionComplete();
-    void fbDump(String8& result);
+    // Get last release fence for the given layer
+    sp<Fence> getLayerReleaseFence(int32_t displayId,
+            const std::shared_ptr<HWC2::Layer>& layer) const;
 
     // Set the output buffer and acquire fence for a virtual display.
-    // Returns INVALID_OPERATION if id is not a virtual display.
-    status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+    // Returns INVALID_OPERATION if displayId is not a virtual display.
+    status_t setOutputBuffer(int32_t displayId, const sp<Fence>& acquireFence,
             const sp<GraphicBuffer>& buf);
 
-    // Get the retire fence for the last committed frame. This fence will
-    // signal when the h/w composer is completely finished with the frame.
-    // For physical displays, it is no longer being displayed. For virtual
-    // displays, writes to the output buffer are complete.
-    sp<Fence> getLastRetireFence(int32_t id) const;
+    // After SurfaceFlinger has retrieved the release fences for all the frames,
+    // it can call this to clear the shared pointers in the release fence map
+    void clearReleaseFences(int32_t displayId);
 
-    status_t setCursorPositionAsync(int32_t id, const Rect &pos);
-
-    /*
-     * Interface to hardware composer's layers functionality.
-     * This abstracts the HAL interface to layers which can evolve in
-     * incompatible ways from one release to another.
-     * The idea is that we could extend this interface as we add
-     * features to h/w composer.
-     */
-    class HWCLayerInterface {
-    protected:
-        virtual ~HWCLayerInterface() { }
-    public:
-        virtual int32_t getCompositionType() const = 0;
-        virtual uint32_t getHints() const = 0;
-        virtual sp<Fence> getAndResetReleaseFence() = 0;
-        virtual void setDefaultState() = 0;
-        virtual void setSkip(bool skip) = 0;
-        virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
-        virtual void setBlending(uint32_t blending) = 0;
-        virtual void setTransform(uint32_t transform) = 0;
-        virtual void setFrame(const Rect& frame) = 0;
-        virtual void setCrop(const FloatRect& crop) = 0;
-        virtual void setVisibleRegionScreen(const Region& reg) = 0;
-        virtual void setSurfaceDamage(const Region& reg) = 0;
-        virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
-        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
-        virtual void setAcquireFenceFd(int fenceFd) = 0;
-        virtual void setPlaneAlpha(uint8_t alpha) = 0;
-        virtual void onDisplayed() = 0;
-    };
-
-    /*
-     * Interface used to implement an iterator to a list
-     * of HWCLayer.
-     */
-    class HWCLayer : public HWCLayerInterface {
-        friend class LayerListIterator;
-        // select the layer at the given index
-        virtual status_t setLayer(size_t index) = 0;
-        virtual HWCLayer* dup() = 0;
-        static HWCLayer* copy(HWCLayer *rhs) {
-            return rhs ? rhs->dup() : NULL;
-        }
-    protected:
-        virtual ~HWCLayer() { }
-    };
-
-    /*
-     * Iterator through a HWCLayer list.
-     * This behaves more or less like a forward iterator.
-     */
-    class LayerListIterator {
-        friend class HWComposer;
-        HWCLayer* const mLayerList;
-        size_t mIndex;
-
-        LayerListIterator() : mLayerList(NULL), mIndex(0) { }
-
-        LayerListIterator(HWCLayer* layer, size_t index)
-            : mLayerList(layer), mIndex(index) { }
-
-        // we don't allow assignment, because we don't need it for now
-        LayerListIterator& operator = (const LayerListIterator& rhs);
-
-    public:
-        // copy operators
-        LayerListIterator(const LayerListIterator& rhs)
-            : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
-        }
-
-        ~LayerListIterator() { delete mLayerList; }
-
-        // pre-increment
-        LayerListIterator& operator++() {
-            mLayerList->setLayer(++mIndex);
-            return *this;
-        }
-
-        // dereference
-        HWCLayerInterface& operator * () { return *mLayerList; }
-        HWCLayerInterface* operator -> () { return mLayerList; }
-
-        // comparison
-        bool operator == (const LayerListIterator& rhs) const {
-            return mIndex == rhs.mIndex;
-        }
-        bool operator != (const LayerListIterator& rhs) const {
-            return !operator==(rhs);
-        }
-    };
-
-    // Returns an iterator to the beginning of the layer list
-    LayerListIterator begin(int32_t id);
-
-    // Returns an iterator to the end of the layer list
-    LayerListIterator end(int32_t id);
-
+    // Returns the HDR capabilities of the given display
+    std::unique_ptr<HdrCapabilities> getHdrCapabilities(int32_t displayId);
 
     // Events handling ---------------------------------------------------------
 
-    enum {
-        EVENT_VSYNC = HWC_EVENT_VSYNC
-    };
-
-    void eventControl(int disp, int event, int enabled);
+    void setVsyncEnabled(int32_t disp, HWC2::Vsync enabled);
 
     struct DisplayConfig {
         uint32_t width;
@@ -262,119 +148,81 @@
 
     // Query display parameters.  Pass in a display index (e.g.
     // HWC_DISPLAY_PRIMARY).
-    nsecs_t getRefreshTimestamp(int disp) const;
-    sp<Fence> getDisplayFence(int disp) const;
-    uint32_t getFormat(int disp) const;
-    bool isConnected(int disp) const;
+    nsecs_t getRefreshTimestamp(int32_t disp) const;
+    bool isConnected(int32_t disp) const;
 
-    // These return the values for the current config of a given display index.
-    // To get the values for all configs, use getConfigs below.
-    uint32_t getWidth(int disp) const;
-    uint32_t getHeight(int disp) const;
-    float getDpiX(int disp) const;
-    float getDpiY(int disp) const;
-    nsecs_t getRefreshPeriod(int disp) const;
+    // Non-const because it can update configMap inside of mDisplayData
+    std::vector<std::shared_ptr<const HWC2::Display::Config>>
+            getConfigs(int32_t displayId) const;
 
-    const Vector<DisplayConfig>& getConfigs(int disp) const;
-    size_t getCurrentConfig(int disp) const;
-
-    status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
-            uint32_t format);
-
-    // this class is only used to fake the VSync event on systems that don't
-    // have it.
-    class VSyncThread : public Thread {
-        HWComposer& mHwc;
-        mutable Mutex mLock;
-        Condition mCondition;
-        bool mEnabled;
-        mutable nsecs_t mNextFakeVSync;
-        nsecs_t mRefreshPeriod;
-        virtual void onFirstRef();
-        virtual bool threadLoop();
-    public:
-        VSyncThread(HWComposer& hwc);
-        void setEnabled(bool enabled);
-    };
-
-    friend class VSyncThread;
+    std::shared_ptr<const HWC2::Display::Config>
+            getActiveConfig(int32_t displayId) const;
 
     // for debugging ----------------------------------------------------------
     void dump(String8& out) const;
 
 private:
-    void loadHwcModule();
-    int loadFbHalModule();
+    static const int32_t VIRTUAL_DISPLAY_ID_BASE = 2;
 
-    LayerListIterator getLayerIterator(int32_t id, size_t index);
+    void loadHwcModule();
+
+    bool isValidDisplay(int32_t displayId) const;
+    static void validateChange(HWC2::Composition from, HWC2::Composition to);
 
     struct cb_context;
 
-    static void hook_invalidate(const struct hwc_procs* procs);
-    static void hook_vsync(const struct hwc_procs* procs, int disp,
+    void invalidate(const std::shared_ptr<HWC2::Display>& display);
+    void vsync(const std::shared_ptr<HWC2::Display>& display,
             int64_t timestamp);
-    static void hook_hotplug(const struct hwc_procs* procs, int disp,
-            int connected);
-
-    inline void invalidate();
-    inline void vsync(int disp, int64_t timestamp);
-    inline void hotplug(int disp, int connected);
-
-    status_t queryDisplayProperties(int disp);
-
-    status_t setFramebufferTarget(int32_t id,
-            const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+    void hotplug(const std::shared_ptr<HWC2::Display>& display,
+            HWC2::Connection connected);
 
     struct DisplayData {
         DisplayData();
         ~DisplayData();
-        Vector<DisplayConfig> configs;
-        size_t currentConfig;
-        uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1
-        bool connected;
-        bool hasFbComp;
-        bool hasOvComp;
-        size_t capacity;
-        hwc_display_contents_1* list;
-        hwc_layer_1* framebufferTarget;
-        buffer_handle_t fbTargetHandle;
+        void reset();
+
+        bool hasClientComposition;
+        bool hasDeviceComposition;
+        std::shared_ptr<HWC2::Display> hwcDisplay;
+        HWC2::DisplayRequest displayRequests;
         sp<Fence> lastRetireFence;  // signals when the last set op retires
-        sp<Fence> lastDisplayFence; // signals when the last set op takes
-                                    // effect on screen
+        std::unordered_map<std::shared_ptr<HWC2::Layer>, sp<Fence>>
+                releaseFences;
         buffer_handle_t outbufHandle;
         sp<Fence> outbufAcquireFence;
+        mutable std::unordered_map<int32_t,
+                std::shared_ptr<const HWC2::Display::Config>> configMap;
 
-        // protected by mEventControlLock
-        int32_t events;
+        // protected by mVsyncLock
+        HWC2::Vsync vsyncEnabled;
     };
 
     sp<SurfaceFlinger>              mFlinger;
-    framebuffer_device_t*           mFbDev;
-    struct hwc_composer_device_1*   mHwc;
-    // invariant: mLists[0] != NULL iff mHwc != NULL
-    // mLists[i>0] can be NULL. that display is to be ignored
-    struct hwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];
-    DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];
+    std::unique_ptr<HWC2On1Adapter> mAdapter;
+    std::unique_ptr<HWC2::Device>   mHwcDevice;
+    std::vector<DisplayData>        mDisplayData;
+    std::set<size_t>                mFreeDisplaySlots;
+    std::unordered_map<hwc2_display_t, int32_t> mHwcDisplaySlots;
     // protect mDisplayData from races between prepare and dump
     mutable Mutex mDisplayLock;
-    size_t                          mNumDisplays;
 
     cb_context*                     mCBContext;
-    EventHandler&                   mEventHandler;
+    EventHandler*                   mEventHandler;
     size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
-    sp<VSyncThread>                 mVSyncThread;
-    bool                            mDebugForceFakeVSync;
-    BitSet32                        mAllocatedDisplayIDs;
+    uint32_t                        mRemainingHwcVirtualDisplays;
 
     // protected by mLock
     mutable Mutex mLock;
-    mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+    mutable std::unordered_map<int32_t, nsecs_t> mLastHwVSync;
 
     // thread-safe
-    mutable Mutex mEventControlLock;
+    mutable Mutex mVsyncLock;
 };
 
 // ---------------------------------------------------------------------------
 }; // namespace android
 
 #endif // ANDROID_SF_HWCOMPOSER_H
+
+#endif // #ifdef USE_HWC2
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
new file mode 100644
index 0000000..4afd8a2
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.cpp
@@ -0,0 +1,1337 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <inttypes.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+#include <utils/misc.h>
+#include <utils/NativeHandle.h>
+#include <utils/String8.h>
+#include <utils/Thread.h>
+#include <utils/Trace.h>
+#include <utils/Vector.h>
+
+#include <ui/GraphicBuffer.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
+
+#include <android/configuration.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "HWComposer.h"
+
+#include "../Layer.h"           // needed only for debugging
+#include "../SurfaceFlinger.h"
+
+namespace android {
+
+#define MIN_HWC_HEADER_VERSION HWC_HEADER_VERSION
+
+static uint32_t hwcApiVersion(const hwc_composer_device_1_t* hwc) {
+    uint32_t hwcVersion = hwc->common.version;
+    return hwcVersion & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+}
+
+static uint32_t hwcHeaderVersion(const hwc_composer_device_1_t* hwc) {
+    uint32_t hwcVersion = hwc->common.version;
+    return hwcVersion & HARDWARE_API_VERSION_2_HEADER_MASK;
+}
+
+static bool hwcHasApiVersion(const hwc_composer_device_1_t* hwc,
+        uint32_t version) {
+    return hwcApiVersion(hwc) >= (version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK);
+}
+
+// ---------------------------------------------------------------------------
+
+struct HWComposer::cb_context {
+    struct callbacks : public hwc_procs_t {
+        // these are here to facilitate the transition when adding
+        // new callbacks (an implementation can check for NULL before
+        // calling a new callback).
+        void (*zero[4])(void);
+    };
+    callbacks procs;
+    HWComposer* hwc;
+};
+
+// ---------------------------------------------------------------------------
+
+HWComposer::HWComposer(
+        const sp<SurfaceFlinger>& flinger,
+        EventHandler& handler)
+    : mFlinger(flinger),
+      mFbDev(0), mHwc(0), mNumDisplays(1),
+      mCBContext(new cb_context),
+      mEventHandler(handler),
+      mDebugForceFakeVSync(false)
+{
+    for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {
+        mLists[i] = 0;
+    }
+
+    for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
+        mLastHwVSync[i] = 0;
+        mVSyncCounts[i] = 0;
+    }
+
+    char value[PROPERTY_VALUE_MAX];
+    property_get("debug.sf.no_hw_vsync", value, "0");
+    mDebugForceFakeVSync = atoi(value);
+
+    bool needVSyncThread = true;
+
+    // Note: some devices may insist that the FB HAL be opened before HWC.
+    int fberr = loadFbHalModule();
+    loadHwcModule();
+
+    if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        // close FB HAL if we don't needed it.
+        // FIXME: this is temporary until we're not forced to open FB HAL
+        // before HWC.
+        framebuffer_close(mFbDev);
+        mFbDev = NULL;
+    }
+
+    // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.
+    if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+            && !mFbDev) {
+        ALOGE("ERROR: failed to open framebuffer (%s), aborting",
+                strerror(-fberr));
+        abort();
+    }
+
+    // these display IDs are always reserved
+    for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
+        mAllocatedDisplayIDs.markBit(i);
+    }
+
+    if (mHwc) {
+        ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,
+              (hwcApiVersion(mHwc) >> 24) & 0xff,
+              (hwcApiVersion(mHwc) >> 16) & 0xff);
+        if (mHwc->registerProcs) {
+            mCBContext->hwc = this;
+            mCBContext->procs.invalidate = &hook_invalidate;
+            mCBContext->procs.vsync = &hook_vsync;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+                mCBContext->procs.hotplug = &hook_hotplug;
+            else
+                mCBContext->procs.hotplug = NULL;
+            memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
+            mHwc->registerProcs(mHwc, &mCBContext->procs);
+        }
+
+        // don't need a vsync thread if we have a hardware composer
+        needVSyncThread = false;
+        // always turn vsync off when we start
+        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+
+        // the number of displays we actually have depends on the
+        // hw composer version
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+            // 1.3 adds support for virtual displays
+            mNumDisplays = MAX_HWC_DISPLAYS;
+        } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // 1.1 adds support for multiple displays
+            mNumDisplays = NUM_BUILTIN_DISPLAYS;
+        } else {
+            mNumDisplays = 1;
+        }
+    }
+
+    if (mFbDev) {
+        ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),
+                "should only have fbdev if no hwc or hwc is 1.0");
+
+        DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);
+        disp.connected = true;
+        disp.format = mFbDev->format;
+        DisplayConfig config = DisplayConfig();
+        config.width = mFbDev->width;
+        config.height = mFbDev->height;
+        config.xdpi = mFbDev->xdpi;
+        config.ydpi = mFbDev->ydpi;
+        config.refresh = nsecs_t(1e9 / mFbDev->fps);
+        disp.configs.push_back(config);
+        disp.currentConfig = 0;
+    } else if (mHwc) {
+        // here we're guaranteed to have at least HWC 1.1
+        for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
+            queryDisplayProperties(i);
+        }
+    }
+
+    if (needVSyncThread) {
+        // we don't have VSYNC support, we need to fake it
+        mVSyncThread = new VSyncThread(*this);
+    }
+}
+
+HWComposer::~HWComposer() {
+    if (mHwc) {
+        eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
+    }
+    if (mVSyncThread != NULL) {
+        mVSyncThread->requestExitAndWait();
+    }
+    if (mHwc) {
+        hwc_close_1(mHwc);
+    }
+    if (mFbDev) {
+        framebuffer_close(mFbDev);
+    }
+    delete mCBContext;
+}
+
+// Load and prepare the hardware composer module.  Sets mHwc.
+void HWComposer::loadHwcModule()
+{
+    hw_module_t const* module;
+
+    if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) {
+        ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID);
+        return;
+    }
+
+    int err = hwc_open_1(module, &mHwc);
+    if (err) {
+        ALOGE("%s device failed to initialize (%s)",
+              HWC_HARDWARE_COMPOSER, strerror(-err));
+        return;
+    }
+
+    if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) ||
+            hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION ||
+            hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) {
+        ALOGE("%s device version %#x unsupported, will not be used",
+              HWC_HARDWARE_COMPOSER, mHwc->common.version);
+        hwc_close_1(mHwc);
+        mHwc = NULL;
+        return;
+    }
+}
+
+// Load and prepare the FB HAL, which uses the gralloc module.  Sets mFbDev.
+int HWComposer::loadFbHalModule()
+{
+    hw_module_t const* module;
+
+    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+    if (err != 0) {
+        ALOGE("%s module not found", GRALLOC_HARDWARE_MODULE_ID);
+        return err;
+    }
+
+    return framebuffer_open(module, &mFbDev);
+}
+
+status_t HWComposer::initCheck() const {
+    return mHwc ? NO_ERROR : NO_INIT;
+}
+
+void HWComposer::hook_invalidate(const struct hwc_procs* procs) {
+    cb_context* ctx = reinterpret_cast<cb_context*>(
+            const_cast<hwc_procs_t*>(procs));
+    ctx->hwc->invalidate();
+}
+
+void HWComposer::hook_vsync(const struct hwc_procs* procs, int disp,
+        int64_t timestamp) {
+    cb_context* ctx = reinterpret_cast<cb_context*>(
+            const_cast<hwc_procs_t*>(procs));
+    ctx->hwc->vsync(disp, timestamp);
+}
+
+void HWComposer::hook_hotplug(const struct hwc_procs* procs, int disp,
+        int connected) {
+    cb_context* ctx = reinterpret_cast<cb_context*>(
+            const_cast<hwc_procs_t*>(procs));
+    ctx->hwc->hotplug(disp, connected);
+}
+
+void HWComposer::invalidate() {
+    mFlinger->repaintEverything();
+}
+
+void HWComposer::vsync(int disp, int64_t timestamp) {
+    if (uint32_t(disp) < HWC_NUM_PHYSICAL_DISPLAY_TYPES) {
+        {
+            Mutex::Autolock _l(mLock);
+
+            // There have been reports of HWCs that signal several vsync events
+            // with the same timestamp when turning the display off and on. This
+            // is a bug in the HWC implementation, but filter the extra events
+            // out here so they don't cause havoc downstream.
+            if (timestamp == mLastHwVSync[disp]) {
+                ALOGW("Ignoring duplicate VSYNC event from HWC (t=%" PRId64 ")",
+                        timestamp);
+                return;
+            }
+
+            mLastHwVSync[disp] = timestamp;
+        }
+
+        char tag[16];
+        snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
+        ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
+
+        mEventHandler.onVSyncReceived(disp, timestamp);
+    }
+}
+
+void HWComposer::hotplug(int disp, int connected) {
+    if (disp >= VIRTUAL_DISPLAY_ID_BASE) {
+        ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
+                disp, connected);
+        return;
+    }
+    queryDisplayProperties(disp);
+    // Do not teardown or recreate the primary display
+    if (disp != HWC_DISPLAY_PRIMARY) {
+        mEventHandler.onHotplugReceived(disp, bool(connected));
+    }
+}
+
+static float getDefaultDensity(uint32_t width, uint32_t height) {
+    // Default density is based on TVs: 1080p displays get XHIGH density,
+    // lower-resolution displays get TV density. Maybe eventually we'll need
+    // to update it for 4K displays, though hopefully those just report
+    // accurate DPI information to begin with. This is also used for virtual
+    // displays and even primary displays with older hwcomposers, so be
+    // careful about orientation.
+
+    uint32_t h = width < height ? width : height;
+    if (h >= 1080) return ACONFIGURATION_DENSITY_XHIGH;
+    else           return ACONFIGURATION_DENSITY_TV;
+}
+
+static const uint32_t DISPLAY_ATTRIBUTES[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_COLOR_TRANSFORM,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+#define NUM_DISPLAY_ATTRIBUTES (sizeof(DISPLAY_ATTRIBUTES) / sizeof(DISPLAY_ATTRIBUTES)[0])
+
+static const uint32_t PRE_HWC15_DISPLAY_ATTRIBUTES[] = {
+    HWC_DISPLAY_VSYNC_PERIOD,
+    HWC_DISPLAY_WIDTH,
+    HWC_DISPLAY_HEIGHT,
+    HWC_DISPLAY_DPI_X,
+    HWC_DISPLAY_DPI_Y,
+    HWC_DISPLAY_NO_ATTRIBUTE,
+};
+
+status_t HWComposer::queryDisplayProperties(int disp) {
+
+    LOG_ALWAYS_FATAL_IF(!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+
+    // use zero as default value for unspecified attributes
+    int32_t values[NUM_DISPLAY_ATTRIBUTES - 1];
+    memset(values, 0, sizeof(values));
+
+    const size_t MAX_NUM_CONFIGS = 128;
+    uint32_t configs[MAX_NUM_CONFIGS] = {0};
+    size_t numConfigs = MAX_NUM_CONFIGS;
+    status_t err = mHwc->getDisplayConfigs(mHwc, disp, configs, &numConfigs);
+    if (err != NO_ERROR) {
+        // this can happen if an unpluggable display is not connected
+        mDisplayData[disp].connected = false;
+        return err;
+    }
+
+    mDisplayData[disp].currentConfig = 0;
+    for (size_t c = 0; c < numConfigs; ++c) {
+        err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
+                DISPLAY_ATTRIBUTES, values);
+        // If this is a pre-1.5 HWC, it may not know about color transform, so
+        // try again with a smaller set of attributes
+        if (err != NO_ERROR) {
+            err = mHwc->getDisplayAttributes(mHwc, disp, configs[c],
+                    PRE_HWC15_DISPLAY_ATTRIBUTES, values);
+        }
+        if (err != NO_ERROR) {
+            // we can't get this display's info. turn it off.
+            mDisplayData[disp].connected = false;
+            return err;
+        }
+
+        DisplayConfig config = DisplayConfig();
+        for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+            switch (DISPLAY_ATTRIBUTES[i]) {
+                case HWC_DISPLAY_VSYNC_PERIOD:
+                    config.refresh = nsecs_t(values[i]);
+                    break;
+                case HWC_DISPLAY_WIDTH:
+                    config.width = values[i];
+                    break;
+                case HWC_DISPLAY_HEIGHT:
+                    config.height = values[i];
+                    break;
+                case HWC_DISPLAY_DPI_X:
+                    config.xdpi = values[i] / 1000.0f;
+                    break;
+                case HWC_DISPLAY_DPI_Y:
+                    config.ydpi = values[i] / 1000.0f;
+                    break;
+                case HWC_DISPLAY_COLOR_TRANSFORM:
+                    config.colorTransform = values[i];
+                    break;
+                default:
+                    ALOG_ASSERT(false, "unknown display attribute[%zu] %#x",
+                            i, DISPLAY_ATTRIBUTES[i]);
+                    break;
+            }
+        }
+
+        if (config.xdpi == 0.0f || config.ydpi == 0.0f) {
+            float dpi = getDefaultDensity(config.width, config.height);
+            config.xdpi = dpi;
+            config.ydpi = dpi;
+        }
+
+        mDisplayData[disp].configs.push_back(config);
+    }
+
+    // FIXME: what should we set the format to?
+    mDisplayData[disp].format = HAL_PIXEL_FORMAT_RGBA_8888;
+    mDisplayData[disp].connected = true;
+    return NO_ERROR;
+}
+
+status_t HWComposer::setVirtualDisplayProperties(int32_t id,
+        uint32_t w, uint32_t h, uint32_t format) {
+    if (id < VIRTUAL_DISPLAY_ID_BASE || id >= int32_t(mNumDisplays) ||
+            !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    size_t configId = mDisplayData[id].currentConfig;
+    mDisplayData[id].format = format;
+    DisplayConfig& config = mDisplayData[id].configs.editItemAt(configId);
+    config.width = w;
+    config.height = h;
+    config.xdpi = config.ydpi = getDefaultDensity(w, h);
+    return NO_ERROR;
+}
+
+int32_t HWComposer::allocateDisplayId() {
+    if (mAllocatedDisplayIDs.count() >= mNumDisplays) {
+        return NO_MEMORY;
+    }
+    int32_t id = mAllocatedDisplayIDs.firstUnmarkedBit();
+    mAllocatedDisplayIDs.markBit(id);
+    mDisplayData[id].connected = true;
+    mDisplayData[id].configs.resize(1);
+    mDisplayData[id].currentConfig = 0;
+    return id;
+}
+
+status_t HWComposer::freeDisplayId(int32_t id) {
+    if (id < NUM_BUILTIN_DISPLAYS) {
+        // cannot free the reserved IDs
+        return BAD_VALUE;
+    }
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    mAllocatedDisplayIDs.clearBit(id);
+    mDisplayData[id].connected = false;
+    return NO_ERROR;
+}
+
+nsecs_t HWComposer::getRefreshTimestamp(int disp) const {
+    // this returns the last refresh timestamp.
+    // if the last one is not available, we estimate it based on
+    // the refresh period and whatever closest timestamp we have.
+    Mutex::Autolock _l(mLock);
+    nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    size_t configId = mDisplayData[disp].currentConfig;
+    return now - ((now - mLastHwVSync[disp]) %
+            mDisplayData[disp].configs[configId].refresh);
+}
+
+sp<Fence> HWComposer::getDisplayFence(int disp) const {
+    return mDisplayData[disp].lastDisplayFence;
+}
+
+uint32_t HWComposer::getFormat(int disp) const {
+    if (static_cast<uint32_t>(disp) >= MAX_HWC_DISPLAYS || !mAllocatedDisplayIDs.hasBit(disp)) {
+        return HAL_PIXEL_FORMAT_RGBA_8888;
+    } else {
+        return mDisplayData[disp].format;
+    }
+}
+
+bool HWComposer::isConnected(int disp) const {
+    return mDisplayData[disp].connected;
+}
+
+uint32_t HWComposer::getWidth(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].width;
+}
+
+uint32_t HWComposer::getHeight(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].height;
+}
+
+float HWComposer::getDpiX(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].xdpi;
+}
+
+float HWComposer::getDpiY(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].ydpi;
+}
+
+nsecs_t HWComposer::getRefreshPeriod(int disp) const {
+    size_t currentConfig = mDisplayData[disp].currentConfig;
+    return mDisplayData[disp].configs[currentConfig].refresh;
+}
+
+const Vector<HWComposer::DisplayConfig>& HWComposer::getConfigs(int disp) const {
+    return mDisplayData[disp].configs;
+}
+
+size_t HWComposer::getCurrentConfig(int disp) const {
+    return mDisplayData[disp].currentConfig;
+}
+
+void HWComposer::eventControl(int disp, int event, int enabled) {
+    if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
+        ALOGD("eventControl ignoring event %d on unallocated disp %d (en=%d)",
+              event, disp, enabled);
+        return;
+    }
+    if (event != EVENT_VSYNC) {
+        ALOGW("eventControl got unexpected event %d (disp=%d en=%d)",
+              event, disp, enabled);
+        return;
+    }
+    status_t err = NO_ERROR;
+    if (mHwc && !mDebugForceFakeVSync) {
+        // NOTE: we use our own internal lock here because we have to call
+        // into the HWC with the lock held, and we want to make sure
+        // that even if HWC blocks (which it shouldn't), it won't
+        // affect other threads.
+        Mutex::Autolock _l(mEventControlLock);
+        const int32_t eventBit = 1UL << event;
+        const int32_t newValue = enabled ? eventBit : 0;
+        const int32_t oldValue = mDisplayData[disp].events & eventBit;
+        if (newValue != oldValue) {
+            ATRACE_CALL();
+            err = mHwc->eventControl(mHwc, disp, event, enabled);
+            if (!err) {
+                int32_t& events(mDisplayData[disp].events);
+                events = (events & ~eventBit) | newValue;
+
+                char tag[16];
+                snprintf(tag, sizeof(tag), "HW_VSYNC_ON_%1u", disp);
+                ATRACE_INT(tag, enabled);
+            }
+        }
+        // error here should not happen -- not sure what we should
+        // do if it does.
+        ALOGE_IF(err, "eventControl(%d, %d) failed %s",
+                event, enabled, strerror(-err));
+    }
+
+    if (err == NO_ERROR && mVSyncThread != NULL) {
+        mVSyncThread->setEnabled(enabled);
+    }
+}
+
+status_t HWComposer::createWorkList(int32_t id, size_t numLayers) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+
+    if (mHwc) {
+        DisplayData& disp(mDisplayData[id]);
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // we need space for the HWC_FRAMEBUFFER_TARGET
+            numLayers++;
+        }
+        if (disp.capacity < numLayers || disp.list == NULL) {
+            size_t size = sizeof(hwc_display_contents_1_t)
+                    + numLayers * sizeof(hwc_layer_1_t);
+            free(disp.list);
+            disp.list = (hwc_display_contents_1_t*)malloc(size);
+            disp.capacity = numLayers;
+        }
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            disp.framebufferTarget = &disp.list->hwLayers[numLayers - 1];
+            memset(disp.framebufferTarget, 0, sizeof(hwc_layer_1_t));
+            const DisplayConfig& currentConfig =
+                    disp.configs[disp.currentConfig];
+            const hwc_rect_t r = { 0, 0,
+                    (int) currentConfig.width, (int) currentConfig.height };
+            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+            disp.framebufferTarget->hints = 0;
+            disp.framebufferTarget->flags = 0;
+            disp.framebufferTarget->handle = disp.fbTargetHandle;
+            disp.framebufferTarget->transform = 0;
+            disp.framebufferTarget->blending = HWC_BLENDING_PREMULT;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+                disp.framebufferTarget->sourceCropf.left = 0;
+                disp.framebufferTarget->sourceCropf.top = 0;
+                disp.framebufferTarget->sourceCropf.right =
+                        currentConfig.width;
+                disp.framebufferTarget->sourceCropf.bottom =
+                        currentConfig.height;
+            } else {
+                disp.framebufferTarget->sourceCrop = r;
+            }
+            disp.framebufferTarget->displayFrame = r;
+            disp.framebufferTarget->visibleRegionScreen.numRects = 1;
+            disp.framebufferTarget->visibleRegionScreen.rects =
+                &disp.framebufferTarget->displayFrame;
+            disp.framebufferTarget->acquireFenceFd = -1;
+            disp.framebufferTarget->releaseFenceFd = -1;
+            disp.framebufferTarget->planeAlpha = 0xFF;
+        }
+        disp.list->retireFenceFd = -1;
+        disp.list->flags = HWC_GEOMETRY_CHANGED;
+        disp.list->numHwLayers = numLayers;
+    }
+    return NO_ERROR;
+}
+
+status_t HWComposer::setFramebufferTarget(int32_t id,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return BAD_INDEX;
+    }
+    DisplayData& disp(mDisplayData[id]);
+    if (!disp.framebufferTarget) {
+        // this should never happen, but apparently eglCreateWindowSurface()
+        // triggers a Surface::queueBuffer()  on some
+        // devices (!?) -- log and ignore.
+        ALOGE("HWComposer: framebufferTarget is null");
+        return NO_ERROR;
+    }
+
+    int acquireFenceFd = -1;
+    if (acquireFence->isValid()) {
+        acquireFenceFd = acquireFence->dup();
+    }
+
+    // ALOGD("fbPost: handle=%p, fence=%d", buf->handle, acquireFenceFd);
+    disp.fbTargetHandle = buf->handle;
+    disp.framebufferTarget->handle = disp.fbTargetHandle;
+    disp.framebufferTarget->acquireFenceFd = acquireFenceFd;
+    return NO_ERROR;
+}
+
+status_t HWComposer::prepare() {
+    Mutex::Autolock _l(mDisplayLock);
+    for (size_t i=0 ; i<mNumDisplays ; i++) {
+        DisplayData& disp(mDisplayData[i]);
+        if (disp.framebufferTarget) {
+            // make sure to reset the type to HWC_FRAMEBUFFER_TARGET
+            // DO NOT reset the handle field to NULL, because it's possible
+            // that we have nothing to redraw (eg: eglSwapBuffers() not called)
+            // in which case, we should continue to use the same buffer.
+            LOG_FATAL_IF(disp.list == NULL);
+            disp.framebufferTarget->compositionType = HWC_FRAMEBUFFER_TARGET;
+        }
+        if (!disp.connected && disp.list != NULL) {
+            ALOGW("WARNING: disp %zu: connected, non-null list, layers=%zu",
+                  i, disp.list->numHwLayers);
+        }
+        mLists[i] = disp.list;
+        if (mLists[i]) {
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+                mLists[i]->outbuf = disp.outbufHandle;
+                mLists[i]->outbufAcquireFenceFd = -1;
+            } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+                // garbage data to catch improper use
+                mLists[i]->dpy = (hwc_display_t)0xDEADBEEF;
+                mLists[i]->sur = (hwc_surface_t)0xDEADBEEF;
+            } else {
+                mLists[i]->dpy = EGL_NO_DISPLAY;
+                mLists[i]->sur = EGL_NO_SURFACE;
+            }
+        }
+    }
+
+    int err = mHwc->prepare(mHwc, mNumDisplays, mLists);
+    ALOGE_IF(err, "HWComposer: prepare failed (%s)", strerror(-err));
+
+    if (err == NO_ERROR) {
+        // here we're just making sure that "skip" layers are set
+        // to HWC_FRAMEBUFFER and we're also counting how many layers
+        // we have of each type.
+        //
+        // If there are no window layers, we treat the display has having FB
+        // composition, because SurfaceFlinger will use GLES to draw the
+        // wormhole region.
+        for (size_t i=0 ; i<mNumDisplays ; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            disp.hasFbComp = false;
+            disp.hasOvComp = false;
+            if (disp.list) {
+                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
+                    hwc_layer_1_t& l = disp.list->hwLayers[i];
+
+                    //ALOGD("prepare: %d, type=%d, handle=%p",
+                    //        i, l.compositionType, l.handle);
+
+                    if (l.flags & HWC_SKIP_LAYER) {
+                        l.compositionType = HWC_FRAMEBUFFER;
+                    }
+                    if (l.compositionType == HWC_FRAMEBUFFER) {
+                        disp.hasFbComp = true;
+                    }
+                    if (l.compositionType == HWC_OVERLAY) {
+                        disp.hasOvComp = true;
+                    }
+                    if (l.compositionType == HWC_CURSOR_OVERLAY) {
+                        disp.hasOvComp = true;
+                    }
+                }
+                if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
+                    disp.hasFbComp = true;
+                }
+            } else {
+                disp.hasFbComp = true;
+            }
+        }
+    }
+    return (status_t)err;
+}
+
+bool HWComposer::hasHwcComposition(int32_t id) const {
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return false;
+    return mDisplayData[id].hasOvComp;
+}
+
+bool HWComposer::hasGlesComposition(int32_t id) const {
+    if (!mHwc || uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return true;
+    return mDisplayData[id].hasFbComp;
+}
+
+sp<Fence> HWComposer::getAndResetReleaseFence(int32_t id) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return Fence::NO_FENCE;
+
+    int fd = INVALID_OPERATION;
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        const DisplayData& disp(mDisplayData[id]);
+        if (disp.framebufferTarget) {
+            fd = disp.framebufferTarget->releaseFenceFd;
+            disp.framebufferTarget->acquireFenceFd = -1;
+            disp.framebufferTarget->releaseFenceFd = -1;
+        }
+    }
+    return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
+}
+
+status_t HWComposer::commit() {
+    int err = NO_ERROR;
+    if (mHwc) {
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+            // On version 1.0, the OpenGL ES target surface is communicated
+            // by the (dpy, sur) fields and we are guaranteed to have only
+            // a single display.
+            mLists[0]->dpy = eglGetCurrentDisplay();
+            mLists[0]->sur = eglGetCurrentSurface(EGL_DRAW);
+        }
+
+        for (size_t i=VIRTUAL_DISPLAY_ID_BASE; i<mNumDisplays; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            if (disp.outbufHandle) {
+                mLists[i]->outbuf = disp.outbufHandle;
+                mLists[i]->outbufAcquireFenceFd =
+                        disp.outbufAcquireFence->dup();
+            }
+        }
+
+        err = mHwc->set(mHwc, mNumDisplays, mLists);
+
+        for (size_t i=0 ; i<mNumDisplays ; i++) {
+            DisplayData& disp(mDisplayData[i]);
+            disp.lastDisplayFence = disp.lastRetireFence;
+            disp.lastRetireFence = Fence::NO_FENCE;
+            if (disp.list) {
+                if (disp.list->retireFenceFd != -1) {
+                    disp.lastRetireFence = new Fence(disp.list->retireFenceFd);
+                    disp.list->retireFenceFd = -1;
+                }
+                disp.list->flags &= ~HWC_GEOMETRY_CHANGED;
+            }
+        }
+    }
+    return (status_t)err;
+}
+
+status_t HWComposer::setPowerMode(int disp, int mode) {
+    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
+    if (mHwc) {
+        if (mode == HWC_POWER_MODE_OFF) {
+            eventControl(disp, HWC_EVENT_VSYNC, 0);
+        }
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+            return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
+        } else {
+            return (status_t)mHwc->blank(mHwc, disp,
+                    mode == HWC_POWER_MODE_OFF ? 1 : 0);
+        }
+    }
+    return NO_ERROR;
+}
+
+status_t HWComposer::setActiveConfig(int disp, int mode) {
+    LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
+    DisplayData& dd(mDisplayData[disp]);
+    dd.currentConfig = mode;
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+        return (status_t)mHwc->setActiveConfig(mHwc, disp, mode);
+    } else {
+        LOG_FATAL_IF(mode != 0);
+    }
+    return NO_ERROR;
+}
+
+void HWComposer::disconnectDisplay(int disp) {
+    LOG_ALWAYS_FATAL_IF(disp < 0 || disp == HWC_DISPLAY_PRIMARY);
+    DisplayData& dd(mDisplayData[disp]);
+    free(dd.list);
+    dd.list = NULL;
+    dd.framebufferTarget = NULL;    // points into dd.list
+    dd.fbTargetHandle = NULL;
+    dd.outbufHandle = NULL;
+    dd.lastRetireFence = Fence::NO_FENCE;
+    dd.lastDisplayFence = Fence::NO_FENCE;
+    dd.outbufAcquireFence = Fence::NO_FENCE;
+    // clear all the previous configs and repopulate when a new
+    // device is added
+    dd.configs.clear();
+}
+
+int HWComposer::getVisualID() const {
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        // FIXME: temporary hack until HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED
+        // is supported by the implementation. we can only be in this case
+        // if we have HWC 1.1
+        return HAL_PIXEL_FORMAT_RGBA_8888;
+        //return HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    } else {
+        return mFbDev->format;
+    }
+}
+
+bool HWComposer::supportsFramebufferTarget() const {
+    return (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1));
+}
+
+int HWComposer::fbPost(int32_t id,
+        const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buffer) {
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+        return setFramebufferTarget(id, acquireFence, buffer);
+    } else {
+        acquireFence->waitForever("HWComposer::fbPost");
+        return mFbDev->post(mFbDev, buffer->handle);
+    }
+}
+
+int HWComposer::fbCompositionComplete() {
+    if (mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))
+        return NO_ERROR;
+
+    if (mFbDev->compositionComplete) {
+        return mFbDev->compositionComplete(mFbDev);
+    } else {
+        return INVALID_OPERATION;
+    }
+}
+
+void HWComposer::fbDump(String8& result) {
+    if (mFbDev && mFbDev->common.version >= 1 && mFbDev->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
+        mFbDev->dump(mFbDev, buffer, SIZE);
+        result.append(buffer);
+    }
+}
+
+status_t HWComposer::setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+        const sp<GraphicBuffer>& buf) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return BAD_INDEX;
+    if (id < VIRTUAL_DISPLAY_ID_BASE)
+        return INVALID_OPERATION;
+
+    DisplayData& disp(mDisplayData[id]);
+    disp.outbufHandle = buf->handle;
+    disp.outbufAcquireFence = acquireFence;
+    return NO_ERROR;
+}
+
+sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id))
+        return Fence::NO_FENCE;
+    return mDisplayData[id].lastRetireFence;
+}
+
+status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
+{
+    if (mHwc->setCursorPositionAsync) {
+        return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
+    }
+    else {
+        return NO_ERROR;
+    }
+}
+
+/*
+ * Helper template to implement a concrete HWCLayer
+ * This holds the pointer to the concrete hwc layer type
+ * and implements the "iterable" side of HWCLayer.
+ */
+template<typename CONCRETE, typename HWCTYPE>
+class Iterable : public HWComposer::HWCLayer {
+protected:
+    HWCTYPE* const mLayerList;
+    HWCTYPE* mCurrentLayer;
+    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer),
+            mIndex(0) { }
+    inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
+    inline HWCTYPE* getLayer() { return mCurrentLayer; }
+    virtual ~Iterable() { }
+    size_t mIndex;
+private:
+    // returns a copy of ourselves
+    virtual HWComposer::HWCLayer* dup() {
+        return new CONCRETE( static_cast<const CONCRETE&>(*this) );
+    }
+    virtual status_t setLayer(size_t index) {
+        mIndex = index;
+        mCurrentLayer = &mLayerList[index];
+        return NO_ERROR;
+    }
+};
+
+/*
+ * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_1_0.
+ * This implements the HWCLayer side of HWCIterableLayer.
+ */
+class HWCLayerVersion1 : public Iterable<HWCLayerVersion1, hwc_layer_1_t> {
+    struct hwc_composer_device_1* mHwc;
+public:
+    HWCLayerVersion1(struct hwc_composer_device_1* hwc, hwc_layer_1_t* layer,
+            Vector<Region>* visibleRegions,
+            Vector<Region>* surfaceDamageRegions)
+        : Iterable<HWCLayerVersion1, hwc_layer_1_t>(layer), mHwc(hwc),
+          mVisibleRegions(visibleRegions),
+          mSurfaceDamageRegions(surfaceDamageRegions) {}
+
+    virtual int32_t getCompositionType() const {
+        return getLayer()->compositionType;
+    }
+    virtual uint32_t getHints() const {
+        return getLayer()->hints;
+    }
+    virtual sp<Fence> getAndResetReleaseFence() {
+        int fd = getLayer()->releaseFenceFd;
+        getLayer()->releaseFenceFd = -1;
+        return fd >= 0 ? new Fence(fd) : Fence::NO_FENCE;
+    }
+    virtual void setAcquireFenceFd(int fenceFd) {
+        getLayer()->acquireFenceFd = fenceFd;
+    }
+    virtual void setPerFrameDefaultState() {
+        //getLayer()->compositionType = HWC_FRAMEBUFFER;
+    }
+    virtual void setPlaneAlpha(uint8_t alpha) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_2)) {
+            getLayer()->planeAlpha = alpha;
+        } else {
+            if (alpha < 0xFF) {
+                getLayer()->flags |= HWC_SKIP_LAYER;
+            }
+        }
+    }
+    virtual void setDefaultState() {
+        hwc_layer_1_t* const l = getLayer();
+        l->compositionType = HWC_FRAMEBUFFER;
+        l->hints = 0;
+        l->flags = HWC_SKIP_LAYER;
+        l->handle = 0;
+        l->transform = 0;
+        l->blending = HWC_BLENDING_NONE;
+        l->visibleRegionScreen.numRects = 0;
+        l->visibleRegionScreen.rects = NULL;
+        l->acquireFenceFd = -1;
+        l->releaseFenceFd = -1;
+        l->planeAlpha = 0xFF;
+    }
+    virtual void setSkip(bool skip) {
+        if (skip) {
+            getLayer()->flags |= HWC_SKIP_LAYER;
+        } else {
+            getLayer()->flags &= ~HWC_SKIP_LAYER;
+        }
+    }
+    virtual void setIsCursorLayerHint(bool isCursor) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+            if (isCursor) {
+                getLayer()->flags |= HWC_IS_CURSOR_LAYER;
+            }
+            else {
+                getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
+            }
+        }
+    }
+    virtual void setBlending(uint32_t blending) {
+        getLayer()->blending = blending;
+    }
+    virtual void setTransform(uint32_t transform) {
+        getLayer()->transform = transform;
+    }
+    virtual void setFrame(const Rect& frame) {
+        getLayer()->displayFrame = reinterpret_cast<hwc_rect_t const&>(frame);
+    }
+    virtual void setCrop(const FloatRect& crop) {
+        if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+            getLayer()->sourceCropf = reinterpret_cast<hwc_frect_t const&>(crop);
+        } else {
+            /*
+             * Since h/w composer didn't support a flot crop rect before version 1.3,
+             * using integer coordinates instead produces a different output from the GL code in
+             * Layer::drawWithOpenGL(). The difference can be large if the buffer crop to
+             * window size ratio is large and a window crop is defined
+             * (i.e.: if we scale the buffer a lot and we also crop it with a window crop).
+             */
+            hwc_rect_t& r = getLayer()->sourceCrop;
+            r.left  = int(ceilf(crop.left));
+            r.top   = int(ceilf(crop.top));
+            r.right = int(floorf(crop.right));
+            r.bottom= int(floorf(crop.bottom));
+        }
+    }
+    virtual void setVisibleRegionScreen(const Region& reg) {
+        hwc_region_t& visibleRegion = getLayer()->visibleRegionScreen;
+        mVisibleRegions->editItemAt(mIndex) = reg;
+        visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(
+                mVisibleRegions->itemAt(mIndex).getArray(
+                &visibleRegion.numRects));
+    }
+    virtual void setSurfaceDamage(const Region& reg) {
+        if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_5)) {
+            return;
+        }
+        hwc_region_t& surfaceDamage = getLayer()->surfaceDamage;
+        // We encode default full-screen damage as INVALID_RECT upstream, but as
+        // 0 rects for HWComposer
+        if (reg.isRect() && reg.getBounds() == Rect::INVALID_RECT) {
+            surfaceDamage.numRects = 0;
+            surfaceDamage.rects = NULL;
+            return;
+        }
+        mSurfaceDamageRegions->editItemAt(mIndex) = reg;
+        surfaceDamage.rects = reinterpret_cast<hwc_rect_t const *>(
+                mSurfaceDamageRegions->itemAt(mIndex).getArray(
+                &surfaceDamage.numRects));
+    }
+    virtual void setSidebandStream(const sp<NativeHandle>& stream) {
+        ALOG_ASSERT(stream->handle() != NULL);
+        getLayer()->compositionType = HWC_SIDEBAND;
+        getLayer()->sidebandStream = stream->handle();
+    }
+    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
+        if (buffer == 0 || buffer->handle == 0) {
+            getLayer()->compositionType = HWC_FRAMEBUFFER;
+            getLayer()->flags |= HWC_SKIP_LAYER;
+            getLayer()->handle = 0;
+        } else {
+            if (getLayer()->compositionType == HWC_SIDEBAND) {
+                // If this was a sideband layer but the stream was removed, reset
+                // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare.
+                getLayer()->compositionType = HWC_FRAMEBUFFER;
+            }
+            getLayer()->handle = buffer->handle;
+        }
+    }
+    virtual void onDisplayed() {
+        getLayer()->acquireFenceFd = -1;
+    }
+
+protected:
+    // Pointers to the vectors of Region backing-memory held in DisplayData.
+    // Only the Region at mIndex corresponds to this Layer.
+    Vector<Region>* mVisibleRegions;
+    Vector<Region>* mSurfaceDamageRegions;
+};
+
+/*
+ * returns an iterator initialized at a given index in the layer list
+ */
+HWComposer::LayerListIterator HWComposer::getLayerIterator(int32_t id, size_t index) {
+    if (uint32_t(id)>31 || !mAllocatedDisplayIDs.hasBit(id)) {
+        return LayerListIterator();
+    }
+    DisplayData& disp(mDisplayData[id]);
+    if (!mHwc || !disp.list || index > disp.list->numHwLayers) {
+        return LayerListIterator();
+    }
+    if (disp.visibleRegions.size() < disp.list->numHwLayers) {
+        disp.visibleRegions.resize(disp.list->numHwLayers);
+    }
+    if (disp.surfaceDamageRegions.size() < disp.list->numHwLayers) {
+        disp.surfaceDamageRegions.resize(disp.list->numHwLayers);
+    }
+    return LayerListIterator(new HWCLayerVersion1(mHwc, disp.list->hwLayers,
+            &disp.visibleRegions, &disp.surfaceDamageRegions), index);
+}
+
+/*
+ * returns an iterator on the beginning of the layer list
+ */
+HWComposer::LayerListIterator HWComposer::begin(int32_t id) {
+    return getLayerIterator(id, 0);
+}
+
+/*
+ * returns an iterator on the end of the layer list
+ */
+HWComposer::LayerListIterator HWComposer::end(int32_t id) {
+    size_t numLayers = 0;
+    if (uint32_t(id) <= 31 && mAllocatedDisplayIDs.hasBit(id)) {
+        const DisplayData& disp(mDisplayData[id]);
+        if (mHwc && disp.list) {
+            numLayers = disp.list->numHwLayers;
+            if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {
+                // with HWC 1.1, the last layer is always the HWC_FRAMEBUFFER_TARGET,
+                // which we ignore when iterating through the layer list.
+                ALOGE_IF(!numLayers, "mDisplayData[%d].list->numHwLayers is 0", id);
+                if (numLayers) {
+                    numLayers--;
+                }
+            }
+        }
+    }
+    return getLayerIterator(id, numLayers);
+}
+
+// Converts a PixelFormat to a human-readable string.  Max 11 chars.
+// (Could use a table of prefab String8 objects.)
+static String8 getFormatStr(PixelFormat format) {
+    switch (format) {
+    case PIXEL_FORMAT_RGBA_8888:    return String8("RGBA_8888");
+    case PIXEL_FORMAT_RGBX_8888:    return String8("RGBx_8888");
+    case PIXEL_FORMAT_RGB_888:      return String8("RGB_888");
+    case PIXEL_FORMAT_RGB_565:      return String8("RGB_565");
+    case PIXEL_FORMAT_BGRA_8888:    return String8("BGRA_8888");
+    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
+                                    return String8("ImplDef");
+    default:
+        String8 result;
+        result.appendFormat("? %08x", format);
+        return result;
+    }
+}
+
+void HWComposer::dump(String8& result) const {
+    Mutex::Autolock _l(mDisplayLock);
+    if (mHwc) {
+        result.appendFormat("Hardware Composer state (version %08x):\n", hwcApiVersion(mHwc));
+        result.appendFormat("  mDebugForceFakeVSync=%d\n", mDebugForceFakeVSync);
+        for (size_t i=0 ; i<mNumDisplays ; i++) {
+            const DisplayData& disp(mDisplayData[i]);
+            if (!disp.connected)
+                continue;
+
+            const Vector< sp<Layer> >& visibleLayersSortedByZ =
+                    mFlinger->getLayerSortedByZForHwcDisplay(i);
+
+
+            result.appendFormat("  Display[%zd] configurations (* current):\n", i);
+            for (size_t c = 0; c < disp.configs.size(); ++c) {
+                const DisplayConfig& config(disp.configs[c]);
+                result.appendFormat("    %s%zd: %ux%u, xdpi=%f, ydpi=%f"
+                        ", refresh=%" PRId64 ", colorTransform=%d\n",
+                        c == disp.currentConfig ? "* " : "", c,
+                        config.width, config.height, config.xdpi, config.ydpi,
+                        config.refresh, config.colorTransform);
+            }
+
+            if (disp.list) {
+                result.appendFormat(
+                        "  numHwLayers=%zu, flags=%08x\n",
+                        disp.list->numHwLayers, disp.list->flags);
+
+                result.append(
+                        "    type   |  handle  | hint | flag | tr | blnd |   format    |     source crop (l,t,r,b)      |          frame         | name \n"
+                        "-----------+----------+------+------+----+------+-------------+--------------------------------+------------------------+------\n");
+                //      " _________ | ________ | ____ | ____ | __ | ____ | ___________ |_____._,_____._,_____._,_____._ |_____,_____,_____,_____ | ___...
+                for (size_t i=0 ; i<disp.list->numHwLayers ; i++) {
+                    const hwc_layer_1_t&l = disp.list->hwLayers[i];
+                    int32_t format = -1;
+                    String8 name("unknown");
+
+                    if (i < visibleLayersSortedByZ.size()) {
+                        const sp<Layer>& layer(visibleLayersSortedByZ[i]);
+                        const sp<GraphicBuffer>& buffer(
+                                layer->getActiveBuffer());
+                        if (buffer != NULL) {
+                            format = buffer->getPixelFormat();
+                        }
+                        name = layer->getName();
+                    }
+
+                    int type = l.compositionType;
+                    if (type == HWC_FRAMEBUFFER_TARGET) {
+                        name = "HWC_FRAMEBUFFER_TARGET";
+                        format = disp.format;
+                    }
+
+                    static char const* compositionTypeName[] = {
+                            "GLES",
+                            "HWC",
+                            "BKGND",
+                            "FB TARGET",
+                            "SIDEBAND",
+                            "HWC_CURSOR",
+                            "UNKNOWN"};
+                    if (type >= NELEM(compositionTypeName))
+                        type = NELEM(compositionTypeName) - 1;
+
+                    String8 formatStr = getFormatStr(format);
+                    if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {
+                        result.appendFormat(
+                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7.1f,%7.1f,%7.1f,%7.1f |%5d,%5d,%5d,%5d | %s\n",
+                                        compositionTypeName[type],
+                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
+                                        l.sourceCropf.left, l.sourceCropf.top, l.sourceCropf.right, l.sourceCropf.bottom,
+                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+                                        name.string());
+                    } else {
+                        result.appendFormat(
+                                " %9s | %08" PRIxPTR " | %04x | %04x | %02x | %04x | %-11s |%7d,%7d,%7d,%7d |%5d,%5d,%5d,%5d | %s\n",
+                                        compositionTypeName[type],
+                                        intptr_t(l.handle), l.hints, l.flags, l.transform, l.blending, formatStr.string(),
+                                        l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
+                                        l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+                                        name.string());
+                    }
+                }
+            }
+        }
+    }
+
+    if (mHwc && mHwc->dump) {
+        const size_t SIZE = 4096;
+        char buffer[SIZE];
+        mHwc->dump(mHwc, buffer, SIZE);
+        result.append(buffer);
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
+    : mHwc(hwc), mEnabled(false),
+      mNextFakeVSync(0),
+      mRefreshPeriod(hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY))
+{
+}
+
+void HWComposer::VSyncThread::setEnabled(bool enabled) {
+    Mutex::Autolock _l(mLock);
+    if (mEnabled != enabled) {
+        mEnabled = enabled;
+        mCondition.signal();
+    }
+}
+
+void HWComposer::VSyncThread::onFirstRef() {
+    run("VSyncThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
+}
+
+bool HWComposer::VSyncThread::threadLoop() {
+    { // scope for lock
+        Mutex::Autolock _l(mLock);
+        while (!mEnabled) {
+            mCondition.wait(mLock);
+        }
+    }
+
+    const nsecs_t period = mRefreshPeriod;
+    const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+    nsecs_t next_vsync = mNextFakeVSync;
+    nsecs_t sleep = next_vsync - now;
+    if (sleep < 0) {
+        // we missed, find where the next vsync should be
+        sleep = (period - ((now - next_vsync) % period));
+        next_vsync = now + sleep;
+    }
+    mNextFakeVSync = next_vsync + period;
+
+    struct timespec spec;
+    spec.tv_sec  = next_vsync / 1000000000;
+    spec.tv_nsec = next_vsync % 1000000000;
+
+    int err;
+    do {
+        err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL);
+    } while (err<0 && errno == EINTR);
+
+    if (err == 0) {
+        mHwc.mEventHandler.onVSyncReceived(0, next_vsync);
+    }
+
+    return true;
+}
+
+HWComposer::DisplayData::DisplayData()
+:   configs(),
+    currentConfig(0),
+    format(HAL_PIXEL_FORMAT_RGBA_8888),
+    connected(false),
+    hasFbComp(false), hasOvComp(false),
+    capacity(0), list(NULL),
+    framebufferTarget(NULL), fbTargetHandle(0),
+    lastRetireFence(Fence::NO_FENCE), lastDisplayFence(Fence::NO_FENCE),
+    outbufHandle(NULL), outbufAcquireFence(Fence::NO_FENCE),
+    events(0)
+{}
+
+HWComposer::DisplayData::~DisplayData() {
+    free(list);
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
new file mode 100644
index 0000000..c861817
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposer_hwc1.h
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SF_HWCOMPOSER_HWC1_H
+#define ANDROID_SF_HWCOMPOSER_HWC1_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <hardware/hwcomposer_defs.h>
+
+#include <ui/Fence.h>
+
+#include <utils/BitSet.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <utils/StrongPointer.h>
+#include <utils/Thread.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
+extern "C" int clock_nanosleep(clockid_t clock_id, int flags,
+                           const struct timespec *request,
+                           struct timespec *remain);
+
+struct hwc_composer_device_1;
+struct hwc_display_contents_1;
+struct hwc_layer_1;
+struct hwc_procs;
+struct framebuffer_device_t;
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class Fence;
+class FloatRect;
+class GraphicBuffer;
+class NativeHandle;
+class Region;
+class String8;
+class SurfaceFlinger;
+
+class HWComposer
+{
+public:
+    class EventHandler {
+        friend class HWComposer;
+        virtual void onVSyncReceived(int disp, nsecs_t timestamp) = 0;
+        virtual void onHotplugReceived(int disp, bool connected) = 0;
+    protected:
+        virtual ~EventHandler() {}
+    };
+
+    enum {
+        NUM_BUILTIN_DISPLAYS = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
+        MAX_HWC_DISPLAYS = HWC_NUM_DISPLAY_TYPES,
+        VIRTUAL_DISPLAY_ID_BASE = HWC_DISPLAY_VIRTUAL,
+    };
+
+    HWComposer(
+            const sp<SurfaceFlinger>& flinger,
+            EventHandler& handler);
+
+    ~HWComposer();
+
+    status_t initCheck() const;
+
+    // Returns a display ID starting at VIRTUAL_DISPLAY_ID_BASE, this ID is to
+    // be used with createWorkList (and all other methods requiring an ID
+    // below).
+    // IDs below NUM_BUILTIN_DISPLAYS are pre-defined and therefore are
+    // always valid.
+    // Returns -1 if an ID cannot be allocated
+    int32_t allocateDisplayId();
+
+    // Recycles the given virtual display ID and frees the associated worklist.
+    // IDs below NUM_BUILTIN_DISPLAYS are not recycled.
+    status_t freeDisplayId(int32_t id);
+
+
+    // Asks the HAL what it can do
+    status_t prepare();
+
+    // commits the list
+    status_t commit();
+
+    // set power mode
+    status_t setPowerMode(int disp, int mode);
+
+    // set active config
+    status_t setActiveConfig(int disp, int mode);
+
+    // reset state when an external, non-virtual display is disconnected
+    void disconnectDisplay(int disp);
+
+    // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
+    status_t createWorkList(int32_t id, size_t numLayers);
+
+    bool supportsFramebufferTarget() const;
+
+    // does this display have layers handled by HWC
+    bool hasHwcComposition(int32_t id) const;
+
+    // does this display have layers handled by GLES
+    bool hasGlesComposition(int32_t id) const;
+
+    // get the releaseFence file descriptor for a display's framebuffer layer.
+    // the release fence is only valid after commit()
+    sp<Fence> getAndResetReleaseFence(int32_t id);
+
+    // needed forward declarations
+    class LayerListIterator;
+
+    // return the visual id to be used to find a suitable EGLConfig for
+    // *ALL* displays.
+    int getVisualID() const;
+
+    // Forwarding to FB HAL for pre-HWC-1.1 code (see FramebufferSurface).
+    int fbPost(int32_t id, const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+    int fbCompositionComplete();
+    void fbDump(String8& result);
+
+    // Set the output buffer and acquire fence for a virtual display.
+    // Returns INVALID_OPERATION if id is not a virtual display.
+    status_t setOutputBuffer(int32_t id, const sp<Fence>& acquireFence,
+            const sp<GraphicBuffer>& buf);
+
+    // Get the retire fence for the last committed frame. This fence will
+    // signal when the h/w composer is completely finished with the frame.
+    // For physical displays, it is no longer being displayed. For virtual
+    // displays, writes to the output buffer are complete.
+    sp<Fence> getLastRetireFence(int32_t id) const;
+
+    status_t setCursorPositionAsync(int32_t id, const Rect &pos);
+
+    /*
+     * Interface to hardware composer's layers functionality.
+     * This abstracts the HAL interface to layers which can evolve in
+     * incompatible ways from one release to another.
+     * The idea is that we could extend this interface as we add
+     * features to h/w composer.
+     */
+    class HWCLayerInterface {
+    protected:
+        virtual ~HWCLayerInterface() { }
+    public:
+        virtual int32_t getCompositionType() const = 0;
+        virtual uint32_t getHints() const = 0;
+        virtual sp<Fence> getAndResetReleaseFence() = 0;
+        virtual void setDefaultState() = 0;
+        virtual void setSkip(bool skip) = 0;
+        virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
+        virtual void setBlending(uint32_t blending) = 0;
+        virtual void setTransform(uint32_t transform) = 0;
+        virtual void setFrame(const Rect& frame) = 0;
+        virtual void setCrop(const FloatRect& crop) = 0;
+        virtual void setVisibleRegionScreen(const Region& reg) = 0;
+        virtual void setSurfaceDamage(const Region& reg) = 0;
+        virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0;
+        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
+        virtual void setAcquireFenceFd(int fenceFd) = 0;
+        virtual void setPlaneAlpha(uint8_t alpha) = 0;
+        virtual void onDisplayed() = 0;
+    };
+
+    /*
+     * Interface used to implement an iterator to a list
+     * of HWCLayer.
+     */
+    class HWCLayer : public HWCLayerInterface {
+        friend class LayerListIterator;
+        // select the layer at the given index
+        virtual status_t setLayer(size_t index) = 0;
+        virtual HWCLayer* dup() = 0;
+        static HWCLayer* copy(HWCLayer *rhs) {
+            return rhs ? rhs->dup() : NULL;
+        }
+    protected:
+        virtual ~HWCLayer() { }
+    };
+
+    /*
+     * Iterator through a HWCLayer list.
+     * This behaves more or less like a forward iterator.
+     */
+    class LayerListIterator {
+        friend class HWComposer;
+        HWCLayer* const mLayerList;
+        size_t mIndex;
+
+        LayerListIterator() : mLayerList(NULL), mIndex(0) { }
+
+        LayerListIterator(HWCLayer* layer, size_t index)
+            : mLayerList(layer), mIndex(index) { }
+
+        // we don't allow assignment, because we don't need it for now
+        LayerListIterator& operator = (const LayerListIterator& rhs);
+
+    public:
+        // copy operators
+        LayerListIterator(const LayerListIterator& rhs)
+            : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
+        }
+
+        ~LayerListIterator() { delete mLayerList; }
+
+        // pre-increment
+        LayerListIterator& operator++() {
+            mLayerList->setLayer(++mIndex);
+            return *this;
+        }
+
+        // dereference
+        HWCLayerInterface& operator * () { return *mLayerList; }
+        HWCLayerInterface* operator -> () { return mLayerList; }
+
+        // comparison
+        bool operator == (const LayerListIterator& rhs) const {
+            return mIndex == rhs.mIndex;
+        }
+        bool operator != (const LayerListIterator& rhs) const {
+            return !operator==(rhs);
+        }
+    };
+
+    // Returns an iterator to the beginning of the layer list
+    LayerListIterator begin(int32_t id);
+
+    // Returns an iterator to the end of the layer list
+    LayerListIterator end(int32_t id);
+
+
+    // Events handling ---------------------------------------------------------
+
+    enum {
+        EVENT_VSYNC = HWC_EVENT_VSYNC
+    };
+
+    void eventControl(int disp, int event, int enabled);
+
+    struct DisplayConfig {
+        uint32_t width;
+        uint32_t height;
+        float xdpi;
+        float ydpi;
+        nsecs_t refresh;
+        int colorTransform;
+    };
+
+    // Query display parameters.  Pass in a display index (e.g.
+    // HWC_DISPLAY_PRIMARY).
+    nsecs_t getRefreshTimestamp(int disp) const;
+    sp<Fence> getDisplayFence(int disp) const;
+    uint32_t getFormat(int disp) const;
+    bool isConnected(int disp) const;
+
+    // These return the values for the current config of a given display index.
+    // To get the values for all configs, use getConfigs below.
+    uint32_t getWidth(int disp) const;
+    uint32_t getHeight(int disp) const;
+    float getDpiX(int disp) const;
+    float getDpiY(int disp) const;
+    nsecs_t getRefreshPeriod(int disp) const;
+
+    const Vector<DisplayConfig>& getConfigs(int disp) const;
+    size_t getCurrentConfig(int disp) const;
+
+    status_t setVirtualDisplayProperties(int32_t id, uint32_t w, uint32_t h,
+            uint32_t format);
+
+    // this class is only used to fake the VSync event on systems that don't
+    // have it.
+    class VSyncThread : public Thread {
+        HWComposer& mHwc;
+        mutable Mutex mLock;
+        Condition mCondition;
+        bool mEnabled;
+        mutable nsecs_t mNextFakeVSync;
+        nsecs_t mRefreshPeriod;
+        virtual void onFirstRef();
+        virtual bool threadLoop();
+    public:
+        VSyncThread(HWComposer& hwc);
+        void setEnabled(bool enabled);
+    };
+
+    friend class VSyncThread;
+
+    // for debugging ----------------------------------------------------------
+    void dump(String8& out) const;
+
+private:
+    void loadHwcModule();
+    int loadFbHalModule();
+
+    LayerListIterator getLayerIterator(int32_t id, size_t index);
+
+    struct cb_context;
+
+    static void hook_invalidate(const struct hwc_procs* procs);
+    static void hook_vsync(const struct hwc_procs* procs, int disp,
+            int64_t timestamp);
+    static void hook_hotplug(const struct hwc_procs* procs, int disp,
+            int connected);
+
+    inline void invalidate();
+    inline void vsync(int disp, int64_t timestamp);
+    inline void hotplug(int disp, int connected);
+
+    status_t queryDisplayProperties(int disp);
+
+    status_t setFramebufferTarget(int32_t id,
+            const sp<Fence>& acquireFence, const sp<GraphicBuffer>& buf);
+
+    struct DisplayData {
+        DisplayData();
+        ~DisplayData();
+        Vector<DisplayConfig> configs;
+        size_t currentConfig;
+        uint32_t format;    // pixel format from FB hal, for pre-hwc-1.1
+        bool connected;
+        bool hasFbComp;
+        bool hasOvComp;
+        size_t capacity;
+        hwc_display_contents_1* list;
+        hwc_layer_1* framebufferTarget;
+        buffer_handle_t fbTargetHandle;
+        sp<Fence> lastRetireFence;  // signals when the last set op retires
+        sp<Fence> lastDisplayFence; // signals when the last set op takes
+                                    // effect on screen
+        buffer_handle_t outbufHandle;
+        sp<Fence> outbufAcquireFence;
+
+        // protected by mEventControlLock
+        int32_t events;
+
+        // We need to hold "copies" of these for memory management purposes. The
+        // actual hwc_layer_1_t holds pointers to the memory within. Vector<>
+        // internally doesn't copy the memory unless one of the copies is
+        // modified.
+        Vector<Region> visibleRegions;
+        Vector<Region> surfaceDamageRegions;
+    };
+
+    sp<SurfaceFlinger>              mFlinger;
+    framebuffer_device_t*           mFbDev;
+    struct hwc_composer_device_1*   mHwc;
+    // invariant: mLists[0] != NULL iff mHwc != NULL
+    // mLists[i>0] can be NULL. that display is to be ignored
+    struct hwc_display_contents_1*  mLists[MAX_HWC_DISPLAYS];
+    DisplayData                     mDisplayData[MAX_HWC_DISPLAYS];
+    // protect mDisplayData from races between prepare and dump
+    mutable Mutex mDisplayLock;
+    size_t                          mNumDisplays;
+
+    cb_context*                     mCBContext;
+    EventHandler&                   mEventHandler;
+    size_t                          mVSyncCounts[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+    sp<VSyncThread>                 mVSyncThread;
+    bool                            mDebugForceFakeVSync;
+    BitSet32                        mAllocatedDisplayIDs;
+
+    // protected by mLock
+    mutable Mutex mLock;
+    mutable nsecs_t mLastHwVSync[HWC_NUM_PHYSICAL_DISPLAY_TYPES];
+
+    // thread-safe
+    mutable Mutex mEventControlLock;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index ba4c198..bc8dfbb 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -19,6 +19,7 @@
 #include "HWComposer.h"
 
 #include <gui/BufferItem.h>
+#include <gui/IProducerListener.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -56,8 +57,20 @@
     mHwc(hwc),
     mDisplayId(dispId),
     mDisplayName(name),
+    mSource{},
+    mDefaultOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+    mOutputFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
     mOutputUsage(GRALLOC_USAGE_HW_COMPOSER),
     mProducerSlotSource(0),
+    mProducerBuffers(),
+    mQueueBufferOutput(),
+    mSinkBufferWidth(0),
+    mSinkBufferHeight(0),
+    mCompositionType(COMPOSITION_UNKNOWN),
+    mFbFence(Fence::NO_FENCE),
+    mOutputFence(Fence::NO_FENCE),
+    mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
+    mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
     mDbgState(DBG_STATE_IDLE),
     mDbgLastCompositionType(COMPOSITION_UNKNOWN),
     mMustRecompose(false)
@@ -92,10 +105,13 @@
     mConsumer->setConsumerName(ConsumerBase::mName);
     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_COMPOSER);
     mConsumer->setDefaultBufferSize(sinkWidth, sinkHeight);
-    mConsumer->setDefaultMaxBufferCount(2);
+    sink->setAsyncMode(true);
+    IGraphicBufferProducer::QueueBufferOutput output;
+    mSource[SOURCE_SCRATCH]->connect(NULL, NATIVE_WINDOW_API_EGL, false, &output);
 }
 
 VirtualDisplaySurface::~VirtualDisplaySurface() {
+    mSource[SOURCE_SCRATCH]->disconnect(NATIVE_WINDOW_API_EGL);
 }
 
 status_t VirtualDisplaySurface::beginFrame(bool mustRecompose) {
@@ -159,9 +175,11 @@
     return NO_ERROR;
 }
 
+#ifndef USE_HWC2
 status_t VirtualDisplaySurface::compositionComplete() {
     return NO_ERROR;
 }
+#endif
 
 status_t VirtualDisplaySurface::advanceFrame() {
     if (mDisplayId < 0)
@@ -202,7 +220,13 @@
 
     status_t result = NO_ERROR;
     if (fbBuffer != NULL) {
+#ifdef USE_HWC2
+        // TODO: Correctly propagate the dataspace from GL composition
+        result = mHwc.setClientTarget(mDisplayId, mFbFence, fbBuffer,
+                HAL_DATASPACE_UNKNOWN);
+#else
         result = mHwc.fbPost(mDisplayId, mFbFence, fbBuffer);
+#endif
     }
 
     return result;
@@ -216,13 +240,22 @@
             "Unexpected onFrameCommitted() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_IDLE;
 
+#ifdef USE_HWC2
+    sp<Fence> retireFence = mHwc.getRetireFence(mDisplayId);
+#else
     sp<Fence> fbFence = mHwc.getAndResetReleaseFence(mDisplayId);
+#endif
     if (mCompositionType == COMPOSITION_MIXED && mFbProducerSlot >= 0) {
         // release the scratch buffer back to the pool
         Mutex::Autolock lock(mMutex);
         int sslot = mapProducer2SourceSlot(SOURCE_SCRATCH, mFbProducerSlot);
         VDS_LOGV("onFrameCommitted: release scratch sslot=%d", sslot);
+#ifdef USE_HWC2
+        addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot],
+                retireFence);
+#else
         addReleaseFenceLocked(sslot, mProducerBuffers[mFbProducerSlot], fbFence);
+#endif
         releaseBufferLocked(sslot, mProducerBuffers[mFbProducerSlot],
                 EGL_NO_DISPLAY, EGL_NO_SYNC_KHR);
     }
@@ -230,7 +263,9 @@
     if (mOutputProducerSlot >= 0) {
         int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
         QueueBufferOutput qbo;
+#ifndef USE_HWC2
         sp<Fence> outFence = mHwc.getLastRetireFence(mDisplayId);
+#endif
         VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
         if (mMustRecompose) {
             status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
@@ -239,8 +274,11 @@
                         HAL_DATASPACE_UNKNOWN,
                         Rect(mSinkBufferWidth, mSinkBufferHeight),
                         NATIVE_WINDOW_SCALING_MODE_FREEZE, 0 /* transform */,
-                        true /* async*/,
+#ifdef USE_HWC2
+                        retireFence),
+#else
                         outFence),
+#endif
                     &qbo);
             if (result == NO_ERROR) {
                 updateQueueBufferOutput(qbo);
@@ -250,7 +288,11 @@
             // through the motions of updating the display to keep our state
             // machine happy. We cancel the buffer to avoid triggering another
             // re-composition and causing an infinite loop.
+#ifdef USE_HWC2
+            mSource[SOURCE_SINK]->cancelBuffer(sslot, retireFence);
+#else
             mSource[SOURCE_SINK]->cancelBuffer(sslot, outFence);
+#endif
         }
     }
 
@@ -269,6 +311,10 @@
     mSinkBufferHeight = h;
 }
 
+const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
+    return mFbFence;
+}
+
 status_t VirtualDisplaySurface::requestBuffer(int pslot,
         sp<GraphicBuffer>* outBuf) {
     if (mDisplayId < 0)
@@ -282,17 +328,20 @@
     return NO_ERROR;
 }
 
-status_t VirtualDisplaySurface::setBufferCount(int bufferCount) {
-    return mSource[SOURCE_SINK]->setBufferCount(bufferCount);
+status_t VirtualDisplaySurface::setMaxDequeuedBufferCount(
+        int maxDequeuedBuffers) {
+    return mSource[SOURCE_SINK]->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+}
+
+status_t VirtualDisplaySurface::setAsyncMode(bool async) {
+    return mSource[SOURCE_SINK]->setAsyncMode(async);
 }
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
         PixelFormat format, uint32_t usage, int* sslot, sp<Fence>* fence) {
     LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
-    // Don't let a slow consumer block us
-    bool async = (source == SOURCE_SINK);
 
-    status_t result = mSource[source]->dequeueBuffer(sslot, fence, async,
+    status_t result = mSource[source]->dequeueBuffer(sslot, fence,
             mSinkBufferWidth, mSinkBufferHeight, format, usage);
     if (result < 0)
         return result;
@@ -331,16 +380,15 @@
     return result;
 }
 
-status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
+status_t VirtualDisplaySurface::dequeueBuffer(int* pslot, sp<Fence>* fence,
         uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
     if (mDisplayId < 0)
-        return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, async, w, h, format, usage);
+        return mSource[SOURCE_SINK]->dequeueBuffer(pslot, fence, w, h, format, usage);
 
     VDS_LOGW_IF(mDbgState != DBG_STATE_PREPARED,
             "Unexpected dequeueBuffer() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_GLES;
 
-    VDS_LOGW_IF(!async, "EGL called dequeueBuffer with !async despite eglSwapInterval(0)");
     VDS_LOGV("dequeueBuffer %dx%d fmt=%d usage=%#x", w, h, format, usage);
 
     status_t result = NO_ERROR;
@@ -442,11 +490,11 @@
         result = acquireBufferLocked(&item, 0);
         if (result != NO_ERROR)
             return result;
-        VDS_LOGW_IF(item.mBuf != sslot,
+        VDS_LOGW_IF(item.mSlot != sslot,
                 "queueBuffer: acquired sslot %d from SCRATCH after queueing sslot %d",
-                item.mBuf, sslot);
-        mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mBuf);
-        mFbFence = mSlots[item.mBuf].mFence;
+                item.mSlot, sslot);
+        mFbProducerSlot = mapSource2ProducerSlot(SOURCE_SCRATCH, item.mSlot);
+        mFbFence = mSlots[item.mSlot].mFence;
 
     } else {
         LOG_FATAL_IF(mCompositionType != COMPOSITION_GLES,
@@ -460,9 +508,8 @@
         Rect crop;
         int scalingMode;
         uint32_t transform;
-        bool async;
         input.deflate(&timestamp, &isAutoTimestamp, &dataSpace, &crop,
-                &scalingMode, &transform, &async, &mFbFence);
+                &scalingMode, &transform, &mFbFence);
 
         mFbProducerSlot = pslot;
         mOutputFence = mFbFence;
@@ -472,7 +519,8 @@
     return NO_ERROR;
 }
 
-void VirtualDisplaySurface::cancelBuffer(int pslot, const sp<Fence>& fence) {
+status_t VirtualDisplaySurface::cancelBuffer(int pslot,
+        const sp<Fence>& fence) {
     if (mDisplayId < 0)
         return mSource[SOURCE_SINK]->cancelBuffer(mapProducer2SourceSlot(SOURCE_SINK, pslot), fence);
 
@@ -520,9 +568,8 @@
     return INVALID_OPERATION;
 }
 
-void VirtualDisplaySurface::allocateBuffers(bool /* async */,
-        uint32_t /* width */, uint32_t /* height */, PixelFormat /* format */,
-        uint32_t /* usage */) {
+void VirtualDisplaySurface::allocateBuffers(uint32_t /* width */,
+        uint32_t /* height */, PixelFormat /* format */, uint32_t /* usage */) {
     // TODO: Should we actually allocate buffers for a virtual display?
 }
 
@@ -539,6 +586,32 @@
     return String8("VirtualDisplaySurface");
 }
 
+uint64_t VirtualDisplaySurface::getNextFrameNumber() const {
+    return 0;
+}
+
+status_t VirtualDisplaySurface::setSharedBufferMode(bool /*sharedBufferMode*/) {
+    ALOGE("setSharedBufferMode not supported on VirtualDisplaySurface");
+    return INVALID_OPERATION;
+}
+
+status_t VirtualDisplaySurface::setAutoRefresh(bool /*autoRefresh*/) {
+    ALOGE("setAutoRefresh not supported on VirtualDisplaySurface");
+    return INVALID_OPERATION;
+}
+
+status_t VirtualDisplaySurface::setDequeueTimeout(nsecs_t /* timeout */) {
+    ALOGE("setDequeueTimeout not supported on VirtualDisplaySurface");
+    return INVALID_OPERATION;
+}
+
+status_t VirtualDisplaySurface::getLastQueuedBuffer(
+        sp<GraphicBuffer>* /*outBuffer*/, sp<Fence>* /*outFence*/,
+        float[16] /* outTransformMatrix*/) {
+    ALOGE("getLastQueuedBuffer not supported on VirtualDisplaySurface");
+    return INVALID_OPERATION;
+}
+
 void VirtualDisplaySurface::updateQueueBufferOutput(
         const QueueBufferOutput& qbo) {
     uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 6298751..29563b6 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -83,11 +83,14 @@
     //
     virtual status_t beginFrame(bool mustRecompose);
     virtual status_t prepareFrame(CompositionType compositionType);
+#ifndef USE_HWC2
     virtual status_t compositionComplete();
+#endif
     virtual status_t advanceFrame();
     virtual void onFrameCommitted();
     virtual void dumpAsString(String8& result) const;
     virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+    virtual const sp<Fence>& getClientTargetAcquireFence() const override;
 
 private:
     enum Source {SOURCE_SINK = 0, SOURCE_SCRATCH = 1};
@@ -98,26 +101,33 @@
     // IGraphicBufferProducer interface, used by the GLES driver.
     //
     virtual status_t requestBuffer(int pslot, sp<GraphicBuffer>* outBuf);
-    virtual status_t setBufferCount(int bufferCount);
-    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, bool async,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+    virtual status_t setAsyncMode(bool async);
+    virtual status_t dequeueBuffer(int* pslot, sp<Fence>* fence, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t usage);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
     virtual status_t attachBuffer(int* slot, const sp<GraphicBuffer>& buffer);
     virtual status_t queueBuffer(int pslot,
             const QueueBufferInput& input, QueueBufferOutput* output);
-    virtual void cancelBuffer(int pslot, const sp<Fence>& fence);
+    virtual status_t cancelBuffer(int pslot, const sp<Fence>& fence);
     virtual int query(int what, int* value);
     virtual status_t connect(const sp<IProducerListener>& listener,
             int api, bool producerControlledByApp, QueueBufferOutput* output);
     virtual status_t disconnect(int api);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
+    virtual uint64_t getNextFrameNumber() const override;
+    virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
+    virtual status_t setAutoRefresh(bool autoRefresh) override;
+    virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
 
     //
     // Utility methods
@@ -244,4 +254,3 @@
 // ---------------------------------------------------------------------------
 
 #endif // ANDROID_SF_VIRTUAL_DISPLAY_SURFACE_H
-
diff --git a/services/surfaceflinger/EventControlThread.cpp b/services/surfaceflinger/EventControlThread.cpp
index 6504091..ee6e886 100644
--- a/services/surfaceflinger/EventControlThread.cpp
+++ b/services/surfaceflinger/EventControlThread.cpp
@@ -35,8 +35,12 @@
 
     bool vsyncEnabled = mVsyncEnabled;
 
+#ifdef USE_HWC2
+    mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
+#else
     mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC,
             mVsyncEnabled);
+#endif
 
     while (true) {
         status_t err = mCond.wait(mMutex);
@@ -47,8 +51,12 @@
         }
 
         if (vsyncEnabled != mVsyncEnabled) {
+#ifdef USE_HWC2
+            mFlinger->setVsyncEnabled(HWC_DISPLAY_PRIMARY, mVsyncEnabled);
+#else
             mFlinger->eventControl(HWC_DISPLAY_PRIMARY,
                     SurfaceFlinger::EVENT_VSYNC, mVsyncEnabled);
+#endif
             vsyncEnabled = mVsyncEnabled;
         }
     }
diff --git a/services/surfaceflinger/EventLog/EventLogTags.logtags b/services/surfaceflinger/EventLog/EventLogTags.logtags
index 791e0e4..6c851dd 100644
--- a/services/surfaceflinger/EventLog/EventLogTags.logtags
+++ b/services/surfaceflinger/EventLog/EventLogTags.logtags
@@ -36,6 +36,7 @@
 # 60100 - 60199 reserved for surfaceflinger
 
 60100 sf_frame_dur (window|3),(dur0|1),(dur1|1),(dur2|1),(dur3|1),(dur4|1),(dur5|1),(dur6|1)
+60110 sf_stop_bootanim (time|2|3)
 
 # NOTE - the range 1000000-2000000 is reserved for partners and others who
 # want to define their own log tags without conflicting with the core platform.
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index f760200..dd88adb 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -44,8 +44,9 @@
     return;
 }
 
-EventThread::EventThread(const sp<VSyncSource>& src)
+EventThread::EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger)
     : mVSyncSource(src),
+      mFlinger(flinger),
       mUseSoftwareVSync(false),
       mVsyncEnabled(false),
       mDebugVsyncEnabled(false),
@@ -126,6 +127,9 @@
 void EventThread::requestNextVsync(
         const sp<EventThread::Connection>& connection) {
     Mutex::Autolock _l(mLock);
+
+    mFlinger.resyncWithRateLimit();
+
     if (connection->count < 0) {
         connection->count = 0;
         mCondition.broadcast();
diff --git a/services/surfaceflinger/EventThread.h b/services/surfaceflinger/EventThread.h
index 9ba179a..34654fa 100644
--- a/services/surfaceflinger/EventThread.h
+++ b/services/surfaceflinger/EventThread.h
@@ -77,7 +77,7 @@
 
 public:
 
-    EventThread(const sp<VSyncSource>& src);
+    EventThread(const sp<VSyncSource>& src, SurfaceFlinger& flinger);
 
     sp<Connection> createEventConnection() const;
     status_t registerDisplayEventConnection(const sp<Connection>& connection);
@@ -116,6 +116,7 @@
     // constants
     sp<VSyncSource> mVSyncSource;
     PowerHAL mPowerHAL;
+    SurfaceFlinger& mFlinger;
 
     mutable Mutex mLock;
     mutable Condition mCondition;
diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp
new file mode 100644
index 0000000..885d712
--- /dev/null
+++ b/services/surfaceflinger/FenceTracker.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <inttypes.h>
+#include "FenceTracker.h"
+#include "Layer.h"
+#include <utils/Trace.h>
+
+namespace android {
+
+FenceTracker::FenceTracker() :
+        mFrameCounter(0),
+        mOffset(0),
+        mFrames() {}
+
+void FenceTracker::dump(String8* outString) {
+    Mutex::Autolock lock(mMutex);
+    checkFencesForCompletion();
+
+    for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) {
+        int index = (mOffset + i) % MAX_FRAME_HISTORY;
+        const FrameRecord& frame = mFrames[index];
+
+        outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId);
+        outString->appendFormat("- Refresh start\t%" PRId64 "\n",
+                frame.refreshStartTime);
+
+        if (frame.glesCompositionDoneTime) {
+            outString->appendFormat("- GLES done\t%" PRId64 "\n",
+                    frame.glesCompositionDoneTime);
+        } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
+            outString->append("- GLES done\tNot signaled\n");
+        }
+        if (frame.retireTime) {
+            outString->appendFormat("- Retire\t%" PRId64 "\n",
+                    frame.retireTime);
+        } else {
+            outString->append("- Retire\tNot signaled\n");
+        }
+        for (const auto& kv : frame.layers) {
+            const LayerRecord& layer = kv.second;
+            outString->appendFormat("-- %s\n", layer.name.string());
+            outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n",
+                    layer.frameNumber,
+                    layer.isGlesComposition ? "GLES" : "HWC");
+            outString->appendFormat("---- Posted\t%" PRId64 "\n",
+                    layer.postedTime);
+            if (layer.acquireTime) {
+                outString->appendFormat("---- Acquire\t%" PRId64 "\n",
+                        layer.acquireTime);
+            } else {
+                outString->append("---- Acquire\tNot signaled\n");
+            }
+            if (layer.releaseTime) {
+                outString->appendFormat("---- Release\t%" PRId64 "\n",
+                        layer.releaseTime);
+            } else {
+                outString->append("---- Release\tNot signaled\n");
+            }
+        }
+    }
+}
+
+static inline bool isValidTimestamp(nsecs_t time) {
+    return time > 0 && time < INT64_MAX;
+}
+
+void FenceTracker::checkFencesForCompletion() {
+    ATRACE_CALL();
+    for (auto& frame : mFrames) {
+        if (frame.retireFence != Fence::NO_FENCE) {
+            nsecs_t time = frame.retireFence->getSignalTime();
+            if (isValidTimestamp(time)) {
+                frame.retireTime = time;
+                frame.retireFence = Fence::NO_FENCE;
+            }
+        }
+        if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
+            nsecs_t time = frame.glesCompositionDoneFence->getSignalTime();
+            if (isValidTimestamp(time)) {
+                frame.glesCompositionDoneTime = time;
+                frame.glesCompositionDoneFence = Fence::NO_FENCE;
+            }
+        }
+        for (auto& kv : frame.layers) {
+            LayerRecord& layer = kv.second;
+            if (layer.acquireFence != Fence::NO_FENCE) {
+                nsecs_t time = layer.acquireFence->getSignalTime();
+                if (isValidTimestamp(time)) {
+                    layer.acquireTime = time;
+                    layer.acquireFence = Fence::NO_FENCE;
+                }
+            }
+            if (layer.releaseFence != Fence::NO_FENCE) {
+                nsecs_t time = layer.releaseFence->getSignalTime();
+                if (isValidTimestamp(time)) {
+                    layer.releaseTime = time;
+                    layer.releaseFence = Fence::NO_FENCE;
+                }
+            }
+        }
+    }
+}
+
+void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
+        const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mMutex);
+    FrameRecord& frame = mFrames[mOffset];
+    FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) %
+                                     MAX_FRAME_HISTORY];
+    frame.layers.clear();
+
+    bool wasGlesCompositionDone = false;
+    const size_t count = layers.size();
+    for (size_t i = 0; i < count; i++) {
+        String8 name;
+        uint64_t frameNumber;
+        bool glesComposition;
+        nsecs_t postedTime;
+        sp<Fence> acquireFence;
+        sp<Fence> prevReleaseFence;
+        int32_t key = layers[i]->getSequence();
+
+        layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
+                &postedTime, &acquireFence, &prevReleaseFence);
+#ifdef USE_HWC2
+        if (glesComposition) {
+            frame.layers.emplace(std::piecewise_construct,
+                    std::forward_as_tuple(key),
+                    std::forward_as_tuple(name, frameNumber, glesComposition,
+                    postedTime, 0, 0, acquireFence, prevReleaseFence));
+            wasGlesCompositionDone = true;
+        } else {
+            frame.layers.emplace(std::piecewise_construct,
+                    std::forward_as_tuple(key),
+                    std::forward_as_tuple(name, frameNumber, glesComposition,
+                    postedTime, 0, 0, acquireFence, Fence::NO_FENCE));
+
+            auto prevLayer = prevFrame.layers.find(key);
+            if (prevLayer != prevFrame.layers.end()) {
+                prevLayer->second.releaseFence = prevReleaseFence;
+            }
+        }
+#else
+        frame.layers.emplace(std::piecewise_construct,
+                std::forward_as_tuple(key),
+                std::forward_as_tuple(name, frameNumber, glesComposition,
+                postedTime, 0, 0, acquireFence,
+                glesComposition ? Fence::NO_FENCE : prevReleaseFence));
+        if (glesComposition) {
+            wasGlesCompositionDone = true;
+        }
+#endif
+        frame.layers.emplace(std::piecewise_construct,
+                std::forward_as_tuple(key),
+                std::forward_as_tuple(name, frameNumber, glesComposition,
+                postedTime, 0, 0, acquireFence, prevReleaseFence));
+    }
+
+    frame.frameId = mFrameCounter;
+    frame.refreshStartTime = refreshStartTime;
+    frame.retireTime = 0;
+    frame.glesCompositionDoneTime = 0;
+    prevFrame.retireFence = retireFence;
+    frame.retireFence = Fence::NO_FENCE;
+    frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
+            Fence::NO_FENCE;
+
+    mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
+    mFrameCounter++;
+
+    checkFencesForCompletion();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h
new file mode 100644
index 0000000..de99820
--- /dev/null
+++ b/services/surfaceflinger/FenceTracker.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_FENCETRACKER_H
+#define ANDROID_FENCETRACKER_H
+
+#include <ui/Fence.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/Timers.h>
+#include <utils/Vector.h>
+
+#include <unordered_map>
+
+namespace android {
+
+class Layer;
+
+/*
+ * Keeps a circular buffer of fence/timestamp data for the last N frames in
+ * SurfaceFlinger. Gets timestamps for fences after they have signaled.
+ */
+class FenceTracker {
+public:
+     FenceTracker();
+     void dump(String8* outString);
+     void addFrame(nsecs_t refreshStartTime, sp<Fence> retireFence,
+             const Vector<sp<Layer>>& layers, sp<Fence> glDoneFence);
+
+protected:
+     static constexpr size_t MAX_FRAME_HISTORY = 128;
+
+     struct LayerRecord {
+         String8 name; // layer name
+         uint64_t frameNumber; // frame number for this layer
+         bool isGlesComposition; // was GLES composition used for this layer?
+         nsecs_t postedTime; // time when buffer was queued
+         nsecs_t acquireTime; // timestamp from the acquire fence
+         nsecs_t releaseTime; // timestamp from the release fence
+         sp<Fence> acquireFence; // acquire fence
+         sp<Fence> releaseFence; // release fence
+
+         LayerRecord(const String8& name, uint64_t frameNumber,
+                 bool isGlesComposition, nsecs_t postedTime,
+                 nsecs_t acquireTime, nsecs_t releaseTime,
+                 sp<Fence> acquireFence, sp<Fence> releaseFence) :
+                 name(name), frameNumber(frameNumber),
+                 isGlesComposition(isGlesComposition), postedTime(postedTime),
+                 acquireTime(acquireTime), releaseTime(releaseTime),
+                 acquireFence(acquireFence), releaseFence(releaseFence) {};
+         LayerRecord() : name("uninitialized"), frameNumber(0),
+                 isGlesComposition(false), postedTime(0), acquireTime(0),
+                 releaseTime(0), acquireFence(Fence::NO_FENCE),
+                 releaseFence(Fence::NO_FENCE) {};
+     };
+
+     struct FrameRecord {
+         // global SurfaceFlinger frame counter
+         uint64_t frameId;
+         // layer data for this frame
+         std::unordered_map<int32_t, LayerRecord> layers;
+         // timestamp for when SurfaceFlinger::handleMessageRefresh() was called
+         nsecs_t refreshStartTime;
+         // timestamp from the retire fence
+         nsecs_t retireTime;
+         // timestamp from the GLES composition completion fence
+         nsecs_t glesCompositionDoneTime;
+         // primary display retire fence for this frame
+         sp<Fence> retireFence;
+         // if GLES composition was done, the fence for its completion
+         sp<Fence> glesCompositionDoneFence;
+
+         FrameRecord() : frameId(0), layers(), refreshStartTime(0),
+                 retireTime(0), glesCompositionDoneTime(0),
+                 retireFence(Fence::NO_FENCE),
+                 glesCompositionDoneFence(Fence::NO_FENCE) {}
+     };
+
+     uint64_t mFrameCounter;
+     uint32_t mOffset;
+     FrameRecord mFrames[MAX_FRAME_HISTORY];
+     Mutex mMutex;
+
+     void checkFencesForCompletion();
+};
+
+}
+
+#endif // ANDROID_FRAMETRACKER_H
diff --git a/services/surfaceflinger/GpuService.cpp b/services/surfaceflinger/GpuService.cpp
new file mode 100644
index 0000000..0c29971
--- /dev/null
+++ b/services/surfaceflinger/GpuService.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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 "GpuService.h"
+
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+#include <vkjson.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+class BpGpuService : public BpInterface<IGpuService>
+{
+public:
+    BpGpuService(const sp<IBinder>& impl) : BpInterface<IGpuService>(impl) {}
+};
+
+IMPLEMENT_META_INTERFACE(GpuService, "android.ui.IGpuService");
+
+status_t BnGpuService::onTransact(uint32_t code, const Parcel& data,
+        Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+    case SHELL_COMMAND_TRANSACTION: {
+        int in = data.readFileDescriptor();
+        int out = data.readFileDescriptor();
+        int err = data.readFileDescriptor();
+        int argc = data.readInt32();
+        Vector<String16> args;
+        for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
+           args.add(data.readString16());
+        }
+        return shellCommand(in, out, err, args);
+    }
+
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+    status_t cmd_help(int out);
+    status_t cmd_vkjson(int out, int err);
+}
+
+const char* const GpuService::SERVICE_NAME = "gpu";
+
+GpuService::GpuService() {}
+
+status_t GpuService::shellCommand(int /*in*/, int out, int err,
+        Vector<String16>& args)
+{
+    ALOGV("GpuService::shellCommand");
+    for (size_t i = 0, n = args.size(); i < n; i++)
+        ALOGV("  arg[%zu]: '%s'", i, String8(args[i]).string());
+
+    if (args[0] == String16("vkjson"))
+        return cmd_vkjson(out, err);
+    else if (args[0] == String16("help"))
+        return cmd_help(out);
+
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+namespace {
+
+status_t cmd_help(int out) {
+    FILE* outs = fdopen(out, "w");
+    if (!outs) {
+        ALOGE("vkjson: failed to create out stream: %s (%d)", strerror(errno),
+            errno);
+        return BAD_VALUE;
+    }
+    fprintf(outs,
+        "GPU Service commands:\n"
+        "  vkjson   dump Vulkan device capabilities as JSON\n");
+    fclose(outs);
+    return NO_ERROR;
+}
+
+VkResult vkjsonPrint(FILE* out, FILE* err) {
+    VkResult result;
+
+    const VkApplicationInfo app_info = {
+        VK_STRUCTURE_TYPE_APPLICATION_INFO, nullptr,
+        "vkjson", 1,    /* app name, version */
+        "", 0,          /* engine name, version */
+        VK_API_VERSION
+    };
+    const VkInstanceCreateInfo instance_info = {
+        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr,
+        0,              /* flags */
+        &app_info,
+        0, nullptr,     /* layers */
+        0, nullptr,     /* extensions */
+    };
+    VkInstance instance;
+    result = vkCreateInstance(&instance_info, nullptr, &instance);
+    if (result != VK_SUCCESS) {
+        fprintf(err, "vkCreateInstance failed: %d\n", result);
+        return result;
+    }
+
+    uint32_t ngpu = 0;
+    result = vkEnumeratePhysicalDevices(instance, &ngpu, nullptr);
+    if (result != VK_SUCCESS) {
+        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
+        return result;
+    }
+    std::vector<VkPhysicalDevice> gpus(ngpu, VK_NULL_HANDLE);
+    result = vkEnumeratePhysicalDevices(instance, &ngpu, gpus.data());
+    if (result != VK_SUCCESS) {
+        fprintf(err, "vkEnumeratePhysicalDevices failed: %d\n", result);
+        return result;
+    }
+
+    for (size_t i = 0, n = gpus.size(); i < n; i++) {
+        auto props = VkJsonGetAllProperties(gpus[i]);
+        std::string json = VkJsonAllPropertiesToJson(props);
+        fwrite(json.data(), 1, json.size(), out);
+        if (i < n - 1)
+            fputc(',', out);
+        fputc('\n', out);
+    }
+
+    vkDestroyInstance(instance, nullptr);
+
+    return VK_SUCCESS;
+}
+
+status_t cmd_vkjson(int out, int err) {
+    int errnum;
+    FILE* outs = fdopen(out, "w");
+    if (!outs) {
+        errnum = errno;
+        ALOGE("vkjson: failed to create output stream: %s", strerror(errnum));
+        return -errnum;
+    }
+    FILE* errs = fdopen(err, "w");
+    if (!errs) {
+        errnum = errno;
+        ALOGE("vkjson: failed to create error stream: %s", strerror(errnum));
+        fclose(outs);
+        return -errnum;
+    }
+    fprintf(outs, "[\n");
+    VkResult result = vkjsonPrint(outs, errs);
+    fprintf(outs, "]\n");
+    fclose(errs);
+    fclose(outs);
+    return result >= 0 ? NO_ERROR : UNKNOWN_ERROR;
+}
+
+} // anonymous namespace
+
+} // namespace android
diff --git a/services/surfaceflinger/GpuService.h b/services/surfaceflinger/GpuService.h
new file mode 100644
index 0000000..b8c28d2
--- /dev/null
+++ b/services/surfaceflinger/GpuService.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_GPUSERVICE_H
+#define ANDROID_GPUSERVICE_H
+
+#include <binder/IInterface.h>
+#include <cutils/compiler.h>
+
+namespace android {
+
+/*
+ * This class defines the Binder IPC interface for GPU-related queries and
+ * control.
+ */
+class IGpuService : public IInterface {
+public:
+    DECLARE_META_INTERFACE(GpuService);
+};
+
+class BnGpuService: public BnInterface<IGpuService> {
+protected:
+    virtual status_t shellCommand(int in, int out, int err,
+        Vector<String16>& args) = 0;
+
+    virtual status_t onTransact(uint32_t code, const Parcel& data,
+            Parcel* reply, uint32_t flags = 0) override;
+};
+
+class GpuService : public BnGpuService
+{
+public:
+    static const char* const SERVICE_NAME ANDROID_API;
+
+    GpuService() ANDROID_API;
+
+protected:
+    virtual status_t shellCommand(int in, int out, int err,
+        Vector<String16>& args) override;
+};
+
+} // namespace android
+
+#endif // ANDROID_GPUSERVICE_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5ff79a9..96252f3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "Layer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <stdlib.h>
@@ -66,16 +69,23 @@
         mName("unnamed"),
         mFormat(PIXEL_FORMAT_NONE),
         mTransactionFlags(0),
+        mPendingStateMutex(),
+        mPendingStates(),
         mQueuedFrames(0),
         mSidebandStreamChanged(false),
         mCurrentTransform(0),
         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
+        mOverrideScalingMode(-1),
         mCurrentOpacity(true),
+        mCurrentFrameNumber(0),
         mRefreshPending(false),
         mFrameLatencyNeeded(false),
         mFiltering(false),
         mNeedsFiltering(false),
         mMesh(Mesh::TRIANGLE_FAN, 4, 2, 2),
+#ifndef USE_HWC2
+        mIsGlesComposition(false),
+#endif
         mProtectedByApp(false),
         mHasSurface(false),
         mClientRef(client),
@@ -84,8 +94,13 @@
         mQueueItemCondition(),
         mQueueItems(),
         mLastFrameNumberReceived(0),
-        mUpdateTexImageFailed(false)
+        mUpdateTexImageFailed(false),
+        mAutoRefresh(false)
 {
+#ifdef USE_HWC2
+    ALOGV("Creating Layer %s", name.string());
+#endif
+
     mCurrentCrop.makeInvalid();
     mFlinger->getRenderEngine().genTextures(1, &mTextureName);
     mTexture.init(Texture::TEXTURE_EXTERNAL, mTextureName);
@@ -105,20 +120,31 @@
 
     mCurrentState.active.w = w;
     mCurrentState.active.h = h;
-    mCurrentState.active.crop.makeInvalid();
+    mCurrentState.active.transform.set(0, 0);
+    mCurrentState.crop.makeInvalid();
+    mCurrentState.finalCrop.makeInvalid();
     mCurrentState.z = 0;
+#ifdef USE_HWC2
+    mCurrentState.alpha = 1.0f;
+#else
     mCurrentState.alpha = 0xFF;
+#endif
     mCurrentState.layerStack = 0;
     mCurrentState.flags = layerFlags;
     mCurrentState.sequence = 0;
-    mCurrentState.transform.set(0, 0);
     mCurrentState.requested = mCurrentState.active;
 
     // drawing state & current state are identical
     mDrawingState = mCurrentState;
 
+#ifdef USE_HWC2
+    const auto& hwc = flinger->getHwComposer();
+    const auto& activeConfig = hwc.getActiveConfig(HWC_DISPLAY_PRIMARY);
+    nsecs_t displayPeriod = activeConfig->getVsyncPeriod();
+#else
     nsecs_t displayPeriod =
             flinger->getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+#endif
     mFrameTracker.setDisplayRefreshPeriod(displayPeriod);
 }
 
@@ -135,9 +161,8 @@
 
 #ifdef TARGET_DISABLE_TRIPLE_BUFFERING
 #warning "disabling triple buffering"
-    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2);
 #else
-    mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3);
+    mProducer->setMaxDequeuedBufferCount(2);
 #endif
 
     const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice());
@@ -145,10 +170,17 @@
 }
 
 Layer::~Layer() {
-    sp<Client> c(mClientRef.promote());
+  sp<Client> c(mClientRef.promote());
     if (c != 0) {
         c->detachLayer(this);
     }
+
+    for (auto& point : mRemoteSyncPoints) {
+        point->setTransactionApplied();
+    }
+    for (auto& point : mLocalSyncPoints) {
+        point->setFrameAvailable();
+    }
     mFlinger->deleteTextureAsync(mTextureName);
     mFrameTracker.logAndResetStats(mName);
 }
@@ -157,6 +189,14 @@
 // callbacks
 // ---------------------------------------------------------------------------
 
+#ifdef USE_HWC2
+void Layer::onLayerDisplayed(const sp<Fence>& releaseFence) {
+    if (mHwcLayers.empty()) {
+        return;
+    }
+    mSurfaceFlingerConsumer->setReleaseFence(releaseFence);
+}
+#else
 void Layer::onLayerDisplayed(const sp<const DisplayDevice>& /* hw */,
         HWComposer::HWCLayerInterface* layer) {
     if (layer) {
@@ -164,6 +204,7 @@
         mSurfaceFlingerConsumer->setReleaseFence(layer->getAndResetReleaseFence());
     }
 }
+#endif
 
 void Layer::onFrameAvailable(const BufferItem& item) {
     // Add this buffer from our internal queue tracker
@@ -197,26 +238,28 @@
 }
 
 void Layer::onFrameReplaced(const BufferItem& item) {
-    Mutex::Autolock lock(mQueueItemLock);
+    { // Autolock scope
+        Mutex::Autolock lock(mQueueItemLock);
 
-    // Ensure that callbacks are handled in order
-    while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
-        status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
-                ms2ns(500));
-        if (result != NO_ERROR) {
-            ALOGE("[%s] Timed out waiting on callback", mName.string());
+        // Ensure that callbacks are handled in order
+        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+                    ms2ns(500));
+            if (result != NO_ERROR) {
+                ALOGE("[%s] Timed out waiting on callback", mName.string());
+            }
         }
-    }
 
-    if (mQueueItems.empty()) {
-        ALOGE("Can't replace a frame on an empty queue");
-        return;
-    }
-    mQueueItems.editItemAt(0) = item;
+        if (mQueueItems.empty()) {
+            ALOGE("Can't replace a frame on an empty queue");
+            return;
+        }
+        mQueueItems.editItemAt(mQueueItems.size() - 1) = item;
 
-    // Wake up any pending callbacks
-    mLastFrameNumberReceived = item.mFrameNumber;
-    mQueueItemCondition.broadcast();
+        // Wake up any pending callbacks
+        mLastFrameNumberReceived = item.mFrameNumber;
+        mQueueItemCondition.broadcast();
+    }
 }
 
 void Layer::onSidebandStreamChanged() {
@@ -267,6 +310,22 @@
     return NO_ERROR;
 }
 
+/*
+ * The layer handle is just a BBinder object passed to the client
+ * (remote process) -- we don't keep any reference on our side such that
+ * the dtor is called when the remote side let go of its reference.
+ *
+ * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
+ * this layer when the handle is destroyed.
+ */
+class Layer::Handle : public BBinder, public LayerCleaner {
+    public:
+        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+            : LayerCleaner(flinger, layer), owner(layer) {}
+
+        wp<Layer> owner;
+};
+
 sp<IBinder> Layer::getHandle() {
     Mutex::Autolock _l(mLock);
 
@@ -275,23 +334,6 @@
 
     mHasSurface = true;
 
-    /*
-     * The layer handle is just a BBinder object passed to the client
-     * (remote process) -- we don't keep any reference on our side such that
-     * the dtor is called when the remote side let go of its reference.
-     *
-     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
-     * this layer when the handle is destroyed.
-     */
-
-    class Handle : public BBinder, public LayerCleaner {
-        wp<const Layer> mOwner;
-    public:
-        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
-            : LayerCleaner(flinger, layer), mOwner(layer) {
-        }
-    };
-
     return new Handle(mFlinger, this);
 }
 
@@ -338,8 +380,9 @@
 Rect Layer::computeBounds(const Region& activeTransparentRegion) const {
     const Layer::State& s(getDrawingState());
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
     return reduce(win, activeTransparentRegion);
@@ -350,7 +393,7 @@
     // layer's size.
     FloatRect crop(getContentCrop());
 
-    // the active.crop is the area of the window that gets cropped, but not
+    // the crop is the area of the window that gets cropped, but not
     // scaled in any ways.
     const State& s(getDrawingState());
 
@@ -362,13 +405,20 @@
     // a viewport clipping and a window transform. we should use floating point to fix this.
 
     Rect activeCrop(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        activeCrop = s.active.crop;
+    if (!s.crop.isEmpty()) {
+        activeCrop = s.crop;
     }
 
-    activeCrop = s.transform.transform(activeCrop);
-    activeCrop.intersect(hw->getViewport(), &activeCrop);
-    activeCrop = s.transform.inverse().transform(activeCrop);
+    activeCrop = s.active.transform.transform(activeCrop);
+    if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+        activeCrop.clear();
+    }
+    if (!s.finalCrop.isEmpty()) {
+        if(!activeCrop.intersect(s.finalCrop, &activeCrop)) {
+            activeCrop.clear();
+        }
+    }
+    activeCrop = s.active.transform.inverse().transform(activeCrop);
 
     // This needs to be here as transform.transform(Rect) computes the
     // transformed rect and then takes the bounding box of the result before
@@ -376,111 +426,152 @@
     // transform.inverse().transform(transform.transform(Rect)) != Rect
     // in which case we need to make sure the final rect is clipped to the
     // display bounds.
-    activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
+    if (!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+        activeCrop.clear();
+    }
 
     // subtract the transparent region and snap to the bounds
     activeCrop = reduce(activeCrop, s.activeTransparentRegion);
 
-    if (!activeCrop.isEmpty()) {
-        // Transform the window crop to match the buffer coordinate system,
-        // which means using the inverse of the current transform set on the
-        // SurfaceFlingerConsumer.
-        uint32_t invTransform = mCurrentTransform;
-        if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
-            /*
-             * the code below applies the display's inverse transform to the buffer
-             */
-            uint32_t invTransformOrient = hw->getOrientationTransform();
-            // calculate the inverse transform
-            if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-                invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                        NATIVE_WINDOW_TRANSFORM_FLIP_H;
-                // If the transform has been rotated the axis of flip has been swapped
-                // so we need to swap which flip operations we are performing
-                bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
-                bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
-                if (is_h_flipped != is_v_flipped) {
-                    invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
-                            NATIVE_WINDOW_TRANSFORM_FLIP_H;
-                }
-            }
-            // and apply to the current transform
-            invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation();
-        }
-
-        int winWidth = s.active.w;
-        int winHeight = s.active.h;
-        if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-            // If the activeCrop has been rotate the ends are rotated but not
-            // the space itself so when transforming ends back we can't rely on
-            // a modification of the axes of rotation. To account for this we
-            // need to reorient the inverse rotation in terms of the current
-            // axes of rotation.
+    // Transform the window crop to match the buffer coordinate system,
+    // which means using the inverse of the current transform set on the
+    // SurfaceFlingerConsumer.
+    uint32_t invTransform = mCurrentTransform;
+    if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
+        /*
+         * the code below applies the primary display's inverse transform to the
+         * buffer
+         */
+        uint32_t invTransformOrient =
+                DisplayDevice::getPrimaryDisplayOrientationTransform();
+        // calculate the inverse transform
+        if (invTransformOrient & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+            invTransformOrient ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+            // If the transform has been rotated the axis of flip has been swapped
+            // so we need to swap which flip operations we are performing
             bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
             bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
-            if (is_h_flipped == is_v_flipped) {
+            if (is_h_flipped != is_v_flipped) {
                 invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
                         NATIVE_WINDOW_TRANSFORM_FLIP_H;
             }
-            winWidth = s.active.h;
-            winHeight = s.active.w;
         }
-        const Rect winCrop = activeCrop.transform(
-                invTransform, s.active.w, s.active.h);
-
-        // below, crop is intersected with winCrop expressed in crop's coordinate space
-        float xScale = crop.getWidth()  / float(winWidth);
-        float yScale = crop.getHeight() / float(winHeight);
-
-        float insetL = winCrop.left                 * xScale;
-        float insetT = winCrop.top                  * yScale;
-        float insetR = (winWidth - winCrop.right )  * xScale;
-        float insetB = (winHeight - winCrop.bottom) * yScale;
-
-        crop.left   += insetL;
-        crop.top    += insetT;
-        crop.right  -= insetR;
-        crop.bottom -= insetB;
+        // and apply to the current transform
+        invTransform = (Transform(invTransform) * Transform(invTransformOrient)).getOrientation();
     }
+
+    int winWidth = s.active.w;
+    int winHeight = s.active.h;
+    if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+        // If the activeCrop has been rotate the ends are rotated but not
+        // the space itself so when transforming ends back we can't rely on
+        // a modification of the axes of rotation. To account for this we
+        // need to reorient the inverse rotation in terms of the current
+        // axes of rotation.
+        bool is_h_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) != 0;
+        bool is_v_flipped = (invTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) != 0;
+        if (is_h_flipped == is_v_flipped) {
+            invTransform ^= NATIVE_WINDOW_TRANSFORM_FLIP_V |
+                    NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        }
+        winWidth = s.active.h;
+        winHeight = s.active.w;
+    }
+    const Rect winCrop = activeCrop.transform(
+            invTransform, s.active.w, s.active.h);
+
+    // below, crop is intersected with winCrop expressed in crop's coordinate space
+    float xScale = crop.getWidth()  / float(winWidth);
+    float yScale = crop.getHeight() / float(winHeight);
+
+    float insetL = winCrop.left                 * xScale;
+    float insetT = winCrop.top                  * yScale;
+    float insetR = (winWidth - winCrop.right )  * xScale;
+    float insetB = (winHeight - winCrop.bottom) * yScale;
+
+    crop.left   += insetL;
+    crop.top    += insetT;
+    crop.right  -= insetR;
+    crop.bottom -= insetB;
+
     return crop;
 }
 
+#ifdef USE_HWC2
+void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice)
+#else
 void Layer::setGeometry(
     const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer)
+#endif
 {
+#ifdef USE_HWC2
+    const auto hwcId = displayDevice->getHwcDisplayId();
+    auto& hwcInfo = mHwcLayers[hwcId];
+#else
     layer.setDefaultState();
+#endif
 
     // enable this layer
+#ifdef USE_HWC2
+    hwcInfo.forceClientComposition = false;
+
+    if (isSecure() && !displayDevice->isSecure()) {
+        hwcInfo.forceClientComposition = true;
+    }
+
+    auto& hwcLayer = hwcInfo.layer;
+#else
     layer.setSkip(false);
 
     if (isSecure() && !hw->isSecure()) {
         layer.setSkip(true);
     }
+#endif
 
     // this gives us only the "orientation" component of the transform
     const State& s(getDrawingState());
+#ifdef USE_HWC2
+    if (!isOpaque(s) || s.alpha != 1.0f) {
+        auto blendMode = mPremultipliedAlpha ?
+                HWC2::BlendMode::Premultiplied : HWC2::BlendMode::Coverage;
+        auto error = hwcLayer->setBlendMode(blendMode);
+        ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set blend mode %s:"
+                " %s (%d)", mName.string(), to_string(blendMode).c_str(),
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+#else
     if (!isOpaque(s) || s.alpha != 0xFF) {
         layer.setBlending(mPremultipliedAlpha ?
                 HWC_BLENDING_PREMULT :
                 HWC_BLENDING_COVERAGE);
     }
+#endif
 
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
     Region activeTransparentRegion(s.activeTransparentRegion);
-    if (!s.active.crop.isEmpty()) {
-        Rect activeCrop(s.active.crop);
-        activeCrop = s.transform.transform(activeCrop);
-        activeCrop.intersect(hw->getViewport(), &activeCrop);
-        activeCrop = s.transform.inverse().transform(activeCrop);
+    if (!s.crop.isEmpty()) {
+        Rect activeCrop(s.crop);
+        activeCrop = s.active.transform.transform(activeCrop);
+#ifdef USE_HWC2
+        if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) {
+#else
+        if(!activeCrop.intersect(hw->getViewport(), &activeCrop)) {
+#endif
+            activeCrop.clear();
+        }
+        activeCrop = s.active.transform.inverse().transform(activeCrop);
         // This needs to be here as transform.transform(Rect) computes the
         // transformed rect and then takes the bounding box of the result before
         // returning. This means
         // transform.inverse().transform(transform.transform(Rect)) != Rect
         // in which case we need to make sure the final rect is clipped to the
         // display bounds.
-        activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop);
+        if(!activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop)) {
+            activeCrop.clear();
+        }
         // mark regions outside the crop as transparent
         activeTransparentRegion.orSelf(Rect(0, 0, s.active.w, activeCrop.top));
         activeTransparentRegion.orSelf(Rect(0, activeCrop.bottom,
@@ -490,12 +581,51 @@
         activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top,
                 s.active.w, activeCrop.bottom));
     }
-    Rect frame(s.transform.transform(computeBounds(activeTransparentRegion)));
-    frame.intersect(hw->getViewport(), &frame);
+    Rect frame(s.active.transform.transform(computeBounds(activeTransparentRegion)));
+    if (!s.finalCrop.isEmpty()) {
+        if(!frame.intersect(s.finalCrop, &frame)) {
+            frame.clear();
+        }
+    }
+#ifdef USE_HWC2
+    if (!frame.intersect(displayDevice->getViewport(), &frame)) {
+        frame.clear();
+    }
+    const Transform& tr(displayDevice->getTransform());
+    Rect transformedFrame = tr.transform(frame);
+    auto error = hwcLayer->setDisplayFrame(transformedFrame);
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set display frame "
+            "[%d, %d, %d, %d]: %s (%d)", mName.string(), transformedFrame.left,
+            transformedFrame.top, transformedFrame.right,
+            transformedFrame.bottom, to_string(error).c_str(),
+            static_cast<int32_t>(error));
+
+    FloatRect sourceCrop = computeCrop(displayDevice);
+    error = hwcLayer->setSourceCrop(sourceCrop);
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set source crop "
+            "[%.3f, %.3f, %.3f, %.3f]: %s (%d)", mName.string(),
+            sourceCrop.left, sourceCrop.top, sourceCrop.right,
+            sourceCrop.bottom, to_string(error).c_str(),
+            static_cast<int32_t>(error));
+
+    error = hwcLayer->setPlaneAlpha(s.alpha);
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set plane alpha %.3f: "
+            "%s (%d)", mName.string(), s.alpha, to_string(error).c_str(),
+            static_cast<int32_t>(error));
+
+    error = hwcLayer->setZOrder(s.z);
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)",
+            mName.string(), s.z, to_string(error).c_str(),
+            static_cast<int32_t>(error));
+#else
+    if (!frame.intersect(hw->getViewport(), &frame)) {
+        frame.clear();
+    }
     const Transform& tr(hw->getTransform());
     layer.setFrame(tr.transform(frame));
     layer.setCrop(computeCrop(hw));
     layer.setPlaneAlpha(s.alpha);
+#endif
 
     /*
      * Transformations are applied in this order:
@@ -506,13 +636,16 @@
      */
 
     const Transform bufferOrientation(mCurrentTransform);
-    Transform transform(tr * s.transform * bufferOrientation);
+    Transform transform(tr * s.active.transform * bufferOrientation);
 
     if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
         /*
-         * the code below applies the display's inverse transform to the buffer
+         * the code below applies the primary display's inverse transform to the
+         * buffer
          */
-        uint32_t invTransform = hw->getOrientationTransform();
+        uint32_t invTransform =
+                DisplayDevice::getPrimaryDisplayOrientationTransform();
+
         uint32_t t_orientation = transform.getOrientation();
         // calculate the inverse transform
         if (invTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
@@ -533,14 +666,110 @@
 
     // this gives us only the "orientation" component of the transform
     const uint32_t orientation = transform.getOrientation();
+#ifdef USE_HWC2
+    if (orientation & Transform::ROT_INVALID) {
+        // we can only handle simple transformation
+        hwcInfo.forceClientComposition = true;
+    } else {
+        auto transform = static_cast<HWC2::Transform>(orientation);
+        auto error = hwcLayer->setTransform(transform);
+        ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set transform %s: "
+                "%s (%d)", mName.string(), to_string(transform).c_str(),
+                to_string(error).c_str(), static_cast<int32_t>(error));
+    }
+#else
     if (orientation & Transform::ROT_INVALID) {
         // we can only handle simple transformation
         layer.setSkip(true);
     } else {
         layer.setTransform(orientation);
     }
+#endif
 }
 
+#ifdef USE_HWC2
+void Layer::forceClientComposition(int32_t hwcId) {
+    if (mHwcLayers.count(hwcId) == 0) {
+        ALOGE("forceClientComposition: no HWC layer found (%d)", hwcId);
+        return;
+    }
+
+    mHwcLayers[hwcId].forceClientComposition = true;
+}
+#endif
+
+#ifdef USE_HWC2
+void Layer::setPerFrameData(const sp<const DisplayDevice>& displayDevice) {
+    // Apply this display's projection's viewport to the visible region
+    // before giving it to the HWC HAL.
+    const Transform& tr = displayDevice->getTransform();
+    const auto& viewport = displayDevice->getViewport();
+    Region visible = tr.transform(visibleRegion.intersect(viewport));
+    auto hwcId = displayDevice->getHwcDisplayId();
+    auto& hwcLayer = mHwcLayers[hwcId].layer;
+    auto error = hwcLayer->setVisibleRegion(visible);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set visible region: %s (%d)", mName.string(),
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        visible.dump(LOG_TAG);
+    }
+
+    error = hwcLayer->setSurfaceDamage(surfaceDamageRegion);
+    if (error != HWC2::Error::None) {
+        ALOGE("[%s] Failed to set surface damage: %s (%d)", mName.string(),
+                to_string(error).c_str(), static_cast<int32_t>(error));
+        surfaceDamageRegion.dump(LOG_TAG);
+    }
+
+    auto compositionType = HWC2::Composition::Invalid;
+    if (mSidebandStream.get()) {
+        compositionType = HWC2::Composition::Sideband;
+        auto error = hwcLayer->setSidebandStream(mSidebandStream->handle());
+        if (error != HWC2::Error::None) {
+            ALOGE("[%s] Failed to set sideband stream %p: %s (%d)",
+                    mName.string(), mSidebandStream->handle(),
+                    to_string(error).c_str(), static_cast<int32_t>(error));
+            return;
+        }
+    } else {
+        if (mActiveBuffer == nullptr || mActiveBuffer->handle == nullptr) {
+            compositionType = HWC2::Composition::Client;
+            auto error = hwcLayer->setBuffer(nullptr, Fence::NO_FENCE);
+            if (error != HWC2::Error::None) {
+                ALOGE("[%s] Failed to set null buffer: %s (%d)", mName.string(),
+                        to_string(error).c_str(), static_cast<int32_t>(error));
+                return;
+            }
+        } else {
+            if (mPotentialCursor) {
+                compositionType = HWC2::Composition::Cursor;
+            }
+            auto acquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+            auto error = hwcLayer->setBuffer(mActiveBuffer->handle,
+                    acquireFence);
+            if (error != HWC2::Error::None) {
+                ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(),
+                        mActiveBuffer->handle, to_string(error).c_str(),
+                        static_cast<int32_t>(error));
+                return;
+            }
+            // If it's not a cursor, default to device composition
+        }
+    }
+
+    if (mHwcLayers[hwcId].forceClientComposition) {
+        ALOGV("[%s] Forcing Client composition", mName.string());
+        setCompositionType(hwcId, HWC2::Composition::Client);
+    } else if (compositionType != HWC2::Composition::Invalid) {
+        ALOGV("[%s] Requesting %s composition", mName.string(),
+                to_string(compositionType).c_str());
+        setCompositionType(hwcId, compositionType);
+    } else {
+        ALOGV("[%s] Requesting Device composition", mName.string());
+        setCompositionType(hwcId, HWC2::Composition::Device);
+    }
+}
+#else
 void Layer::setPerFrameData(const sp<const DisplayDevice>& hw,
         HWComposer::HWCLayerInterface& layer) {
     // we have to set the visible region on every frame because
@@ -552,6 +781,7 @@
     Region visible = tr.transform(visibleRegion.intersect(hw->getViewport()));
     layer.setVisibleRegionScreen(visible);
     layer.setSurfaceDamage(surfaceDamageRegion);
+    mIsGlesComposition = (layer.getCompositionType() == HWC_FRAMEBUFFER);
 
     if (mSidebandStream.get()) {
         layer.setSidebandStream(mSidebandStream);
@@ -561,7 +791,43 @@
         layer.setBuffer(mActiveBuffer);
     }
 }
+#endif
 
+#ifdef USE_HWC2
+void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) {
+    auto hwcId = displayDevice->getHwcDisplayId();
+    if (mHwcLayers.count(hwcId) == 0 ||
+            getCompositionType(hwcId) != HWC2::Composition::Cursor) {
+        return;
+    }
+
+    // This gives us only the "orientation" component of the transform
+    const State& s(getCurrentState());
+
+    // Apply the layer's transform, followed by the display's global transform
+    // Here we're guaranteed that the layer's transform preserves rects
+    Rect win(s.active.w, s.active.h);
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
+    }
+    // Subtract the transparent region and snap to the bounds
+    Rect bounds = reduce(win, s.activeTransparentRegion);
+    Rect frame(s.active.transform.transform(bounds));
+    frame.intersect(displayDevice->getViewport(), &frame);
+    if (!s.finalCrop.isEmpty()) {
+        frame.intersect(s.finalCrop, &frame);
+    }
+    auto& displayTransform(displayDevice->getTransform());
+    auto position = displayTransform.transform(frame);
+
+    auto error = mHwcLayers[hwcId].layer->setCursorPosition(position.left,
+            position.top);
+    ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set cursor position "
+            "to (%d, %d): %s (%d)", mName.string(), position.left,
+            position.top, to_string(error).c_str(),
+            static_cast<int32_t>(error));
+}
+#else
 void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
         HWComposer::HWCLayerInterface& layer) {
     int fenceFd = -1;
@@ -590,16 +856,20 @@
     // apply the layer's transform, followed by the display's global transform
     // here we're guaranteed that the layer's transform preserves rects
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
     Rect bounds = reduce(win, s.activeTransparentRegion);
-    Rect frame(s.transform.transform(bounds));
+    Rect frame(s.active.transform.transform(bounds));
     frame.intersect(hw->getViewport(), &frame);
+    if (!s.finalCrop.isEmpty()) {
+        frame.intersect(s.finalCrop, &frame);
+    }
     const Transform& tr(hw->getTransform());
     return Rect(tr.transform(frame));
 }
+#endif
 
 // ---------------------------------------------------------------------------
 // drawing...
@@ -676,7 +946,8 @@
         if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) {
 
             /*
-             * the code below applies the display's inverse transform to the texture transform
+             * the code below applies the primary display's inverse transform to
+             * the texture transform
              */
 
             // create a 4x4 transform matrix from the display transform flags
@@ -685,7 +956,8 @@
             const mat4 rot90( 0,1,0,0, -1,0,0,0, 0,0,1,0, 1,0,0,1);
 
             mat4 tr;
-            uint32_t transform = hw->getOrientationTransform();
+            uint32_t transform =
+                    DisplayDevice::getPrimaryDisplayOrientationTransform();
             if (transform & NATIVE_WINDOW_TRANSFORM_ROT_90)
                 tr = tr * rot90;
             if (transform & NATIVE_WINDOW_TRANSFORM_FLIP_H)
@@ -750,7 +1022,18 @@
      * minimal value)? Or, we could make GL behave like HWC -- but this feel
      * like more of a hack.
      */
-    const Rect win(computeBounds());
+    Rect win(computeBounds());
+
+    if (!s.finalCrop.isEmpty()) {
+        win = s.active.transform.transform(win);
+        if (!win.intersect(s.finalCrop, &win)) {
+            win.clear();
+        }
+        win = s.active.transform.inverse().transform(win);
+        if (!win.intersect(computeBounds(), &win)) {
+            win.clear();
+        }
+    }
 
     float left   = float(win.left)   / float(s.active.w);
     float top    = float(win.top)    / float(s.active.h);
@@ -771,6 +1054,55 @@
     engine.disableBlending();
 }
 
+#ifdef USE_HWC2
+void Layer::setCompositionType(int32_t hwcId, HWC2::Composition type,
+        bool callIntoHwc) {
+    if (mHwcLayers.count(hwcId) == 0) {
+        ALOGE("setCompositionType called without a valid HWC layer");
+        return;
+    }
+    auto& hwcInfo = mHwcLayers[hwcId];
+    auto& hwcLayer = hwcInfo.layer;
+    ALOGV("setCompositionType(%" PRIx64 ", %s, %d)", hwcLayer->getId(),
+            to_string(type).c_str(), static_cast<int>(callIntoHwc));
+    if (hwcInfo.compositionType != type) {
+        ALOGV("    actually setting");
+        hwcInfo.compositionType = type;
+        if (callIntoHwc) {
+            auto error = hwcLayer->setCompositionType(type);
+            ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set "
+                    "composition type %s: %s (%d)", mName.string(),
+                    to_string(type).c_str(), to_string(error).c_str(),
+                    static_cast<int32_t>(error));
+        }
+    }
+}
+
+HWC2::Composition Layer::getCompositionType(int32_t hwcId) const {
+    if (mHwcLayers.count(hwcId) == 0) {
+        ALOGE("getCompositionType called without a valid HWC layer");
+        return HWC2::Composition::Invalid;
+    }
+    return mHwcLayers.at(hwcId).compositionType;
+}
+
+void Layer::setClearClientTarget(int32_t hwcId, bool clear) {
+    if (mHwcLayers.count(hwcId) == 0) {
+        ALOGE("setClearClientTarget called without a valid HWC layer");
+        return;
+    }
+    mHwcLayers[hwcId].clearClientTarget = clear;
+}
+
+bool Layer::getClearClientTarget(int32_t hwcId) const {
+    if (mHwcLayers.count(hwcId) == 0) {
+        ALOGE("getClearClientTarget called without a valid HWC layer");
+        return false;
+    }
+    return mHwcLayers.at(hwcId).clearClientTarget;
+}
+#endif
+
 uint32_t Layer::getProducerStickyTransform() const {
     int producerStickyTransform = 0;
     int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
@@ -782,6 +1114,27 @@
     return static_cast<uint32_t>(producerStickyTransform);
 }
 
+uint64_t Layer::getHeadFrameNumber() const {
+    Mutex::Autolock lock(mQueueItemLock);
+    if (!mQueueItems.empty()) {
+        return mQueueItems[0].mFrameNumber;
+    } else {
+        return mCurrentFrameNumber;
+    }
+}
+
+bool Layer::addSyncPoint(const std::shared_ptr<SyncPoint>& point) {
+    if (point->getFrameNumber() <= mCurrentFrameNumber) {
+        // Don't bother with a SyncPoint, since we've already latched the
+        // relevant frame
+        return false;
+    }
+
+    Mutex::Autolock lock(mLocalSyncPointMutex);
+    mLocalSyncPoints.push_back(point);
+    return true;
+}
+
 void Layer::setFiltering(bool filtering) {
     mFiltering = filtering;
 }
@@ -814,25 +1167,58 @@
 // local state
 // ----------------------------------------------------------------------------
 
+static void boundPoint(vec2* point, const Rect& crop) {
+    if (point->x < crop.left) {
+        point->x = crop.left;
+    }
+    if (point->x > crop.right) {
+        point->x = crop.right;
+    }
+    if (point->y < crop.top) {
+        point->y = crop.top;
+    }
+    if (point->y > crop.bottom) {
+        point->y = crop.bottom;
+    }
+}
+
 void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh,
         bool useIdentityTransform) const
 {
     const Layer::State& s(getDrawingState());
-    const Transform tr(useIdentityTransform ?
-            hw->getTransform() : hw->getTransform() * s.transform);
+    const Transform tr(hw->getTransform());
     const uint32_t hw_h = hw->getHeight();
     Rect win(s.active.w, s.active.h);
-    if (!s.active.crop.isEmpty()) {
-        win.intersect(s.active.crop, &win);
+    if (!s.crop.isEmpty()) {
+        win.intersect(s.crop, &win);
     }
     // subtract the transparent region and snap to the bounds
     win = reduce(win, s.activeTransparentRegion);
 
+    vec2 lt = vec2(win.left, win.top);
+    vec2 lb = vec2(win.left, win.bottom);
+    vec2 rb = vec2(win.right, win.bottom);
+    vec2 rt = vec2(win.right, win.top);
+
+    if (!useIdentityTransform) {
+        lt = s.active.transform.transform(lt);
+        lb = s.active.transform.transform(lb);
+        rb = s.active.transform.transform(rb);
+        rt = s.active.transform.transform(rt);
+    }
+
+    if (!s.finalCrop.isEmpty()) {
+        boundPoint(&lt, s.finalCrop);
+        boundPoint(&lb, s.finalCrop);
+        boundPoint(&rb, s.finalCrop);
+        boundPoint(&rt, s.finalCrop);
+    }
+
     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
-    position[0] = tr.transform(win.left,  win.top);
-    position[1] = tr.transform(win.left,  win.bottom);
-    position[2] = tr.transform(win.right, win.bottom);
-    position[3] = tr.transform(win.right, win.top);
+    position[0] = tr.transform(lt);
+    position[1] = tr.transform(lb);
+    position[2] = tr.transform(rb);
+    position[3] = tr.transform(rt);
     for (size_t i=0 ; i<4 ; i++) {
         position[i].y = hw_h - position[i].y;
     }
@@ -865,7 +1251,7 @@
 }
 
 bool Layer::isFixedSize() const {
-    return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+    return getEffectiveScalingMode() != NATIVE_WINDOW_SCALING_MODE_FREEZE;
 }
 
 bool Layer::isCropped() const {
@@ -896,11 +1282,122 @@
 // transaction
 // ----------------------------------------------------------------------------
 
+void Layer::pushPendingState() {
+    if (!mCurrentState.modified) {
+        return;
+    }
+
+    // If this transaction is waiting on the receipt of a frame, generate a sync
+    // point and send it to the remote layer.
+    if (mCurrentState.handle != nullptr) {
+        sp<Handle> handle = static_cast<Handle*>(mCurrentState.handle.get());
+        sp<Layer> handleLayer = handle->owner.promote();
+        if (handleLayer == nullptr) {
+            ALOGE("[%s] Unable to promote Layer handle", mName.string());
+            // If we can't promote the layer we are intended to wait on,
+            // then it is expired or otherwise invalid. Allow this transaction
+            // to be applied as per normal (no synchronization).
+            mCurrentState.handle = nullptr;
+        } else {
+            auto syncPoint = std::make_shared<SyncPoint>(
+                    mCurrentState.frameNumber);
+            if (handleLayer->addSyncPoint(syncPoint)) {
+                mRemoteSyncPoints.push_back(std::move(syncPoint));
+            } else {
+                // We already missed the frame we're supposed to synchronize
+                // on, so go ahead and apply the state update
+                mCurrentState.handle = nullptr;
+            }
+        }
+
+        // Wake us up to check if the frame has been received
+        setTransactionFlags(eTransactionNeeded);
+    }
+    mPendingStates.push_back(mCurrentState);
+}
+
+void Layer::popPendingState(State* stateToCommit) {
+    auto oldFlags = stateToCommit->flags;
+    *stateToCommit = mPendingStates[0];
+    stateToCommit->flags = (oldFlags & ~stateToCommit->mask) |
+            (stateToCommit->flags & stateToCommit->mask);
+
+    mPendingStates.removeAt(0);
+}
+
+bool Layer::applyPendingStates(State* stateToCommit) {
+    bool stateUpdateAvailable = false;
+    while (!mPendingStates.empty()) {
+        if (mPendingStates[0].handle != nullptr) {
+            if (mRemoteSyncPoints.empty()) {
+                // If we don't have a sync point for this, apply it anyway. It
+                // will be visually wrong, but it should keep us from getting
+                // into too much trouble.
+                ALOGE("[%s] No local sync point found", mName.string());
+                popPendingState(stateToCommit);
+                stateUpdateAvailable = true;
+                continue;
+            }
+
+            if (mRemoteSyncPoints.front()->getFrameNumber() !=
+                    mPendingStates[0].frameNumber) {
+                ALOGE("[%s] Unexpected sync point frame number found",
+                        mName.string());
+
+                // Signal our end of the sync point and then dispose of it
+                mRemoteSyncPoints.front()->setTransactionApplied();
+                mRemoteSyncPoints.pop_front();
+                continue;
+            }
+
+            if (mRemoteSyncPoints.front()->frameIsAvailable()) {
+                // Apply the state update
+                popPendingState(stateToCommit);
+                stateUpdateAvailable = true;
+
+                // Signal our end of the sync point and then dispose of it
+                mRemoteSyncPoints.front()->setTransactionApplied();
+                mRemoteSyncPoints.pop_front();
+            } else {
+                break;
+            }
+        } else {
+            popPendingState(stateToCommit);
+            stateUpdateAvailable = true;
+        }
+    }
+
+    // If we still have pending updates, wake SurfaceFlinger back up and point
+    // it at this layer so we can process them
+    if (!mPendingStates.empty()) {
+        setTransactionFlags(eTransactionNeeded);
+        mFlinger->setTransactionFlags(eTraversalNeeded);
+    }
+
+    mCurrentState.modified = false;
+    return stateUpdateAvailable;
+}
+
+void Layer::notifyAvailableFrames() {
+    auto headFrameNumber = getHeadFrameNumber();
+    Mutex::Autolock lock(mLocalSyncPointMutex);
+    for (auto& point : mLocalSyncPoints) {
+        if (headFrameNumber >= point->getFrameNumber()) {
+            point->setFrameAvailable();
+        }
+    }
+}
+
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
+    pushPendingState();
+    Layer::State c = getCurrentState();
+    if (!applyPendingStates(&c)) {
+        return 0;
+    }
+
     const Layer::State& s(getDrawingState());
-    const Layer::State& c(getCurrentState());
 
     const bool sizeChanged = (c.requested.w != s.requested.w) ||
                              (c.requested.h != s.requested.h);
@@ -910,38 +1407,27 @@
         ALOGD_IF(DEBUG_RESIZE,
                 "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
                 "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
+                "            requested={ wh={%4u,%4u} }}\n"
                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
-                this, getName().string(), mCurrentTransform, mCurrentScalingMode,
+                "            requested={ wh={%4u,%4u} }}\n",
+                this, getName().string(), mCurrentTransform,
+                getEffectiveScalingMode(),
                 c.active.w, c.active.h,
-                c.active.crop.left,
-                c.active.crop.top,
-                c.active.crop.right,
-                c.active.crop.bottom,
-                c.active.crop.getWidth(),
-                c.active.crop.getHeight(),
+                c.crop.left,
+                c.crop.top,
+                c.crop.right,
+                c.crop.bottom,
+                c.crop.getWidth(),
+                c.crop.getHeight(),
                 c.requested.w, c.requested.h,
-                c.requested.crop.left,
-                c.requested.crop.top,
-                c.requested.crop.right,
-                c.requested.crop.bottom,
-                c.requested.crop.getWidth(),
-                c.requested.crop.getHeight(),
                 s.active.w, s.active.h,
-                s.active.crop.left,
-                s.active.crop.top,
-                s.active.crop.right,
-                s.active.crop.bottom,
-                s.active.crop.getWidth(),
-                s.active.crop.getHeight(),
-                s.requested.w, s.requested.h,
-                s.requested.crop.left,
-                s.requested.crop.top,
-                s.requested.crop.right,
-                s.requested.crop.bottom,
-                s.requested.crop.getWidth(),
-                s.requested.crop.getHeight());
+                s.crop.left,
+                s.crop.top,
+                s.crop.right,
+                s.crop.bottom,
+                s.crop.getWidth(),
+                s.crop.getHeight(),
+                s.requested.w, s.requested.h);
 
         // record the new size, form this point on, when the client request
         // a buffer, it'll get the new size.
@@ -976,8 +1462,7 @@
     // this is used by Layer, which special cases resizes.
     if (flags & eDontUpdateGeometryState)  {
     } else {
-        Layer::State& editCurrentState(getCurrentState());
-        editCurrentState.active = c.requested;
+        c.active = c.requested;
     }
 
     if (s.active != c.active) {
@@ -991,18 +1476,29 @@
         this->contentDirty = true;
 
         // we may use linear filtering, if the matrix scales us
-        const uint8_t type = c.transform.getType();
-        mNeedsFiltering = (!c.transform.preserveRects() ||
+        const uint8_t type = c.active.transform.getType();
+        mNeedsFiltering = (!c.active.transform.preserveRects() ||
                 (type >= Transform::SCALE));
     }
 
+    // If the layer is hidden, signal and clear out all local sync points so
+    // that transactions for layers depending on this layer's frames becoming
+    // visible are not blocked
+    if (c.flags & layer_state_t::eLayerHidden) {
+        Mutex::Autolock lock(mLocalSyncPointMutex);
+        for (auto& point : mLocalSyncPoints) {
+            point->setFrameAvailable();
+        }
+        mLocalSyncPoints.clear();
+    }
+
     // Commit the transaction
-    commitTransaction();
+    commitTransaction(c);
     return flags;
 }
 
-void Layer::commitTransaction() {
-    mDrawingState = mCurrentState;
+void Layer::commitTransaction(const State& stateToCommit) {
+    mDrawingState = stateToCommit;
 }
 
 uint32_t Layer::getTransactionFlags(uint32_t flags) {
@@ -1014,10 +1510,17 @@
 }
 
 bool Layer::setPosition(float x, float y) {
-    if (mCurrentState.transform.tx() == x && mCurrentState.transform.ty() == y)
+    if (mCurrentState.requested.transform.tx() == x && mCurrentState.requested.transform.ty() == y)
         return false;
     mCurrentState.sequence++;
-    mCurrentState.transform.set(x, y);
+
+    // We update the requested and active position simultaneously because
+    // we want to apply the position portion of the transform matrix immediately,
+    // but still delay scaling when resizing a SCALING_MODE_FREEZE layer.
+    mCurrentState.requested.transform.set(x, y);
+    mCurrentState.active.transform.set(x, y);
+
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1026,6 +1529,7 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.z = z;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1034,26 +1538,34 @@
         return false;
     mCurrentState.requested.w = w;
     mCurrentState.requested.h = h;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
+#ifdef USE_HWC2
+bool Layer::setAlpha(float alpha) {
+#else
 bool Layer::setAlpha(uint8_t alpha) {
+#endif
     if (mCurrentState.alpha == alpha)
         return false;
     mCurrentState.sequence++;
     mCurrentState.alpha = alpha;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
     mCurrentState.sequence++;
-    mCurrentState.transform.set(
+    mCurrentState.requested.transform.set(
             matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 bool Layer::setTransparentRegionHint(const Region& transparent) {
     mCurrentState.requestedTransparentRegion = transparent;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1063,27 +1575,67 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.flags = newFlags;
+    mCurrentState.mask = mask;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 bool Layer::setCrop(const Rect& crop) {
-    if (mCurrentState.requested.crop == crop)
+    if (mCurrentState.crop == crop)
         return false;
     mCurrentState.sequence++;
-    mCurrentState.requested.crop = crop;
+    mCurrentState.crop = crop;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
+bool Layer::setFinalCrop(const Rect& crop) {
+    if (mCurrentState.finalCrop == crop)
+        return false;
+    mCurrentState.sequence++;
+    mCurrentState.finalCrop = crop;
+    mCurrentState.modified = true;
+    setTransactionFlags(eTransactionNeeded);
+    return true;
+}
+
+bool Layer::setOverrideScalingMode(int32_t scalingMode) {
+    if (scalingMode == mOverrideScalingMode)
+        return false;
+    mOverrideScalingMode = scalingMode;
+    return true;
+}
+
+uint32_t Layer::getEffectiveScalingMode() const {
+    if (mOverrideScalingMode >= 0) {
+      return mOverrideScalingMode;
+    }
+    return mCurrentScalingMode;
+}
 
 bool Layer::setLayerStack(uint32_t layerStack) {
     if (mCurrentState.layerStack == layerStack)
         return false;
     mCurrentState.sequence++;
     mCurrentState.layerStack = layerStack;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
+void Layer::deferTransactionUntil(const sp<IBinder>& handle,
+        uint64_t frameNumber) {
+    mCurrentState.handle = handle;
+    mCurrentState.frameNumber = frameNumber;
+    // We don't set eTransactionNeeded, because just receiving a deferral
+    // request without any other state updates shouldn't actually induce a delay
+    mCurrentState.modified = true;
+    pushPendingState();
+    mCurrentState.handle = nullptr;
+    mCurrentState.frameNumber = 0;
+    mCurrentState.modified = false;
+}
+
 void Layer::useSurfaceDamage() {
     if (mFlinger->mForceFullDamage) {
         surfaceDamageRegion = Region::INVALID_REGION;
@@ -1101,7 +1653,7 @@
 // ----------------------------------------------------------------------------
 
 bool Layer::shouldPresentNow(const DispSync& dispSync) const {
-    if (mSidebandStreamChanged) {
+    if (mSidebandStreamChanged || mAutoRefresh) {
         return true;
     }
 
@@ -1125,7 +1677,7 @@
 
 bool Layer::onPreComposition() {
     mRefreshPending = false;
-    return mQueuedFrames > 0 || mSidebandStreamChanged;
+    return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
 }
 
 void Layer::onPostComposition() {
@@ -1143,7 +1695,11 @@
         }
 
         const HWComposer& hwc = mFlinger->getHwComposer();
+#ifdef USE_HWC2
+        sp<Fence> presentFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY);
+#else
         sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
+#endif
         if (presentFence->isValid()) {
             mFrameTracker.setActualPresentFence(presentFence);
         } else {
@@ -1158,10 +1714,21 @@
     }
 }
 
+#ifdef USE_HWC2
+void Layer::releasePendingBuffer() {
+    mSurfaceFlingerConsumer->releasePendingBuffer();
+}
+#endif
+
 bool Layer::isVisible() const {
     const Layer::State& s(mDrawingState);
+#ifdef USE_HWC2
+    return !(s.flags & layer_state_t::eLayerHidden) && s.alpha > 0.0f
+            && (mActiveBuffer != NULL || mSidebandStream != NULL);
+#else
     return !(s.flags & layer_state_t::eLayerHidden) && s.alpha
             && (mActiveBuffer != NULL || mSidebandStream != NULL);
+#endif
 }
 
 Region Layer::latchBuffer(bool& recomputeVisibleRegions)
@@ -1178,11 +1745,11 @@
         recomputeVisibleRegions = true;
 
         const State& s(getDrawingState());
-        return s.transform.transform(Region(Rect(s.active.w, s.active.h)));
+        return s.active.transform.transform(Region(Rect(s.active.w, s.active.h)));
     }
 
     Region outDirtyRegion;
-    if (mQueuedFrames > 0) {
+    if (mQueuedFrames > 0 || mAutoRefresh) {
 
         // if we've already called updateTexImage() without going through
         // a composition step, we have to skip this layer at this point
@@ -1203,11 +1770,18 @@
             Layer::State& current;
             bool& recomputeVisibleRegions;
             bool stickyTransformSet;
+            const char* name;
+            int32_t overrideScalingMode;
+
             Reject(Layer::State& front, Layer::State& current,
-                    bool& recomputeVisibleRegions, bool stickySet)
+                    bool& recomputeVisibleRegions, bool stickySet,
+                    const char* name,
+                    int32_t overrideScalingMode)
                 : front(front), current(current),
                   recomputeVisibleRegions(recomputeVisibleRegions),
-                  stickyTransformSet(stickySet) {
+                  stickyTransformSet(stickySet),
+                  name(name),
+                  overrideScalingMode(overrideScalingMode) {
             }
 
             virtual bool reject(const sp<GraphicBuffer>& buf,
@@ -1225,7 +1799,9 @@
                     swap(bufWidth, bufHeight);
                 }
 
-                bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
+                int actualScalingMode = overrideScalingMode >= 0 ?
+                        overrideScalingMode : item.mScalingMode;
+                bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
                 if (front.active != front.requested) {
 
                     if (isFixedSize ||
@@ -1250,32 +1826,28 @@
                     }
 
                     ALOGD_IF(DEBUG_RESIZE,
-                            "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
+                            "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
                             "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
-                            "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
+                            "            requested={ wh={%4u,%4u} }}\n",
+                            name,
                             bufWidth, bufHeight, item.mTransform, item.mScalingMode,
                             front.active.w, front.active.h,
-                            front.active.crop.left,
-                            front.active.crop.top,
-                            front.active.crop.right,
-                            front.active.crop.bottom,
-                            front.active.crop.getWidth(),
-                            front.active.crop.getHeight(),
-                            front.requested.w, front.requested.h,
-                            front.requested.crop.left,
-                            front.requested.crop.top,
-                            front.requested.crop.right,
-                            front.requested.crop.bottom,
-                            front.requested.crop.getWidth(),
-                            front.requested.crop.getHeight());
+                            front.crop.left,
+                            front.crop.top,
+                            front.crop.right,
+                            front.crop.bottom,
+                            front.crop.getWidth(),
+                            front.crop.getHeight(),
+                            front.requested.w, front.requested.h);
                 }
 
                 if (!isFixedSize && !stickyTransformSet) {
                     if (front.active.w != bufWidth ||
                         front.active.h != bufHeight) {
                         // reject this buffer
-                        ALOGE("rejecting buffer: bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
-                                bufWidth, bufHeight, front.active.w, front.active.h);
+                        ALOGE("[%s] rejecting buffer: "
+                                "bufWidth=%d, bufHeight=%d, front.active.{w=%d, h=%d}",
+                                name, bufWidth, bufHeight, front.active.w, front.active.h);
                         return true;
                     }
                 }
@@ -1305,16 +1877,52 @@
         };
 
         Reject r(mDrawingState, getCurrentState(), recomputeVisibleRegions,
-                getProducerStickyTransform() != 0);
+                getProducerStickyTransform() != 0, mName.string(),
+                mOverrideScalingMode);
 
-        uint64_t maxFrameNumber = 0;
+
+        // Check all of our local sync points to ensure that all transactions
+        // which need to have been applied prior to the frame which is about to
+        // be latched have signaled
+
+        auto headFrameNumber = getHeadFrameNumber();
+        bool matchingFramesFound = false;
+        bool allTransactionsApplied = true;
         {
-            Mutex::Autolock lock(mQueueItemLock);
-            maxFrameNumber = mLastFrameNumberReceived;
+            Mutex::Autolock lock(mLocalSyncPointMutex);
+            for (auto& point : mLocalSyncPoints) {
+                if (point->getFrameNumber() > headFrameNumber) {
+                    break;
+                }
+
+                matchingFramesFound = true;
+
+                if (!point->frameIsAvailable()) {
+                    // We haven't notified the remote layer that the frame for
+                    // this point is available yet. Notify it now, and then
+                    // abort this attempt to latch.
+                    point->setFrameAvailable();
+                    allTransactionsApplied = false;
+                    break;
+                }
+
+                allTransactionsApplied &= point->transactionIsApplied();
+            }
         }
 
+        if (matchingFramesFound && !allTransactionsApplied) {
+            mFlinger->signalLayerUpdate();
+            return outDirtyRegion;
+        }
+
+        // This boolean is used to make sure that SurfaceFlinger's shadow copy
+        // of the buffer queue isn't modified when the buffer queue is returning
+        // BufferItem's that weren't actually queued. This can happen in shared
+        // buffer mode.
+        bool queuedBuffer = false;
         status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
-                mFlinger->mPrimaryDispSync, maxFrameNumber);
+                mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
+                mLastFrameNumberReceived);
         if (updateResult == BufferQueue::PRESENT_LATER) {
             // Producer doesn't want buffer to be displayed yet.  Signal a
             // layer update so we check again at the next opportunity.
@@ -1323,16 +1931,18 @@
         } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
             // If the buffer has been rejected, remove it from the shadow queue
             // and return early
-            Mutex::Autolock lock(mQueueItemLock);
-            mQueueItems.removeAt(0);
-            android_atomic_dec(&mQueuedFrames);
+            if (queuedBuffer) {
+                Mutex::Autolock lock(mQueueItemLock);
+                mQueueItems.removeAt(0);
+                android_atomic_dec(&mQueuedFrames);
+            }
             return outDirtyRegion;
         } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
             // This can occur if something goes wrong when trying to create the
             // EGLImage for this buffer. If this happens, the buffer has already
             // been released, so we need to clean up the queue and bug out
             // early.
-            {
+            if (queuedBuffer) {
                 Mutex::Autolock lock(mQueueItemLock);
                 mQueueItems.clear();
                 android_atomic_and(0, &mQueuedFrames);
@@ -1347,7 +1957,8 @@
             return outDirtyRegion;
         }
 
-        { // Autolock scope
+        if (queuedBuffer) {
+            // Autolock scope
             auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
 
             Mutex::Autolock lock(mQueueItemLock);
@@ -1365,7 +1976,8 @@
 
         // Decrement the queued-frames count.  Signal another event if we
         // have more frames pending.
-        if (android_atomic_dec(&mQueuedFrames) > 1) {
+        if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
+                || mAutoRefresh) {
             mFlinger->signalLayerUpdate();
         }
 
@@ -1417,11 +2029,35 @@
             recomputeVisibleRegions = true;
         }
 
+        mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+        // Remove any sync points corresponding to the buffer which was just
+        // latched
+        {
+            Mutex::Autolock lock(mLocalSyncPointMutex);
+            auto point = mLocalSyncPoints.begin();
+            while (point != mLocalSyncPoints.end()) {
+                if (!(*point)->frameIsAvailable() ||
+                        !(*point)->transactionIsApplied()) {
+                    // This sync point must have been added since we started
+                    // latching. Don't drop it yet.
+                    ++point;
+                    continue;
+                }
+
+                if ((*point)->getFrameNumber() <= mCurrentFrameNumber) {
+                    point = mLocalSyncPoints.erase(point);
+                } else {
+                    ++point;
+                }
+            }
+        }
+
         // FIXME: postedRegion should be dirty & bounds
         Region dirtyRegion(Rect(s.active.w, s.active.h));
 
         // transform the dirty region to window-manager space
-        outDirtyRegion = (s.transform.transform(dirtyRegion));
+        outDirtyRegion = (s.active.transform.transform(dirtyRegion));
     }
     return outDirtyRegion;
 }
@@ -1475,17 +2111,24 @@
     sp<Client> client(mClientRef.promote());
 
     result.appendFormat(            "      "
-            "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
+            "layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), "
+            "crop=(%4d,%4d,%4d,%4d), finalCrop=(%4d,%4d,%4d,%4d), "
             "isOpaque=%1d, invalidate=%1d, "
+#ifdef USE_HWC2
+            "alpha=%.3f, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
+#else
             "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
+#endif
             "      client=%p\n",
-            s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
-            s.active.crop.left, s.active.crop.top,
-            s.active.crop.right, s.active.crop.bottom,
+            s.layerStack, s.z, s.active.transform.tx(), s.active.transform.ty(), s.active.w, s.active.h,
+            s.crop.left, s.crop.top,
+            s.crop.right, s.crop.bottom,
+            s.finalCrop.left, s.finalCrop.top,
+            s.finalCrop.right, s.finalCrop.bottom,
             isOpaque(s), contentDirty,
             s.alpha, s.flags,
-            s.transform[0][0], s.transform[0][1],
-            s.transform[1][0], s.transform[1][1],
+            s.active.transform[0][0], s.active.transform[0][1],
+            s.active.transform[1][0], s.active.transform[1][1],
             client.get());
 
     sp<const GraphicBuffer> buf0(mActiveBuffer);
@@ -1524,6 +2167,23 @@
     mFrameTracker.getStats(outStats);
 }
 
+void Layer::getFenceData(String8* outName, uint64_t* outFrameNumber,
+        bool* outIsGlesComposition, nsecs_t* outPostedTime,
+        sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const {
+    *outName = mName;
+    *outFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+#ifdef USE_HWC2
+    *outIsGlesComposition = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ?
+            mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType ==
+            HWC2::Composition::Client : true;
+#else
+    *outIsGlesComposition = mIsGlesComposition;
+#endif
+    *outPostedTime = mSurfaceFlingerConsumer->getTimestamp();
+    *outAcquireFence = mSurfaceFlingerConsumer->getCurrentFence();
+    *outPrevReleaseFence = mSurfaceFlingerConsumer->getPrevReleaseFence();
+}
 // ---------------------------------------------------------------------------
 
 Layer::LayerCleaner::LayerCleaner(const sp<SurfaceFlinger>& flinger,
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c1e5e9f..7d085a4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -36,6 +36,8 @@
 
 #include <private/gui/LayerState.h>
 
+#include <list>
+
 #include "FrameTracker.h"
 #include "Client.h"
 #include "MonitoredProducer.h"
@@ -91,9 +93,10 @@
     struct Geometry {
         uint32_t w;
         uint32_t h;
-        Rect crop;
+        Transform transform;
+
         inline bool operator ==(const Geometry& rhs) const {
-            return (w == rhs.w && h == rhs.h && crop == rhs.crop);
+          return (w == rhs.w && h == rhs.h);
         }
         inline bool operator !=(const Geometry& rhs) const {
             return !operator ==(rhs);
@@ -105,11 +108,25 @@
         Geometry requested;
         uint32_t z;
         uint32_t layerStack;
+#ifdef USE_HWC2
+        float alpha;
+#else
         uint8_t alpha;
+#endif
         uint8_t flags;
+        uint8_t mask;
         uint8_t reserved[2];
         int32_t sequence; // changes when visible regions can change
-        Transform transform;
+        bool modified;
+
+        Rect crop;
+        Rect finalCrop;
+
+        // If set, defers this state update until the Layer identified by handle
+        // receives a frame with the given frameNumber
+        sp<IBinder> handle;
+        uint64_t frameNumber;
+
         // the transparentRegion hint is a bit special, it's latched only
         // when we receive a buffer -- this is because it's "content"
         // dependent.
@@ -131,12 +148,19 @@
     bool setPosition(float x, float y);
     bool setLayer(uint32_t z);
     bool setSize(uint32_t w, uint32_t h);
+#ifdef USE_HWC2
+    bool setAlpha(float alpha);
+#else
     bool setAlpha(uint8_t alpha);
+#endif
     bool setMatrix(const layer_state_t::matrix22_t& matrix);
     bool setTransparentRegionHint(const Region& transparent);
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setCrop(const Rect& crop);
+    bool setFinalCrop(const Rect& crop);
     bool setLayerStack(uint32_t layerStack);
+    void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
+    bool setOverrideScalingMode(int32_t overrideScalingMode);
 
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
@@ -152,10 +176,13 @@
     Rect computeBounds(const Region& activeTransparentRegion) const;
     Rect computeBounds() const;
 
+    class Handle;
     sp<IBinder> getHandle();
     sp<IGraphicBufferProducer> getProducer() const;
     const String8& getName() const;
 
+    int32_t getSequence() const { return sequence; }
+
     // -----------------------------------------------------------------------
     // Virtuals
 
@@ -202,6 +229,22 @@
 public:
     // -----------------------------------------------------------------------
 
+#ifdef USE_HWC2
+    void setGeometry(const sp<const DisplayDevice>& displayDevice);
+    void forceClientComposition(int32_t hwcId);
+    void setPerFrameData(const sp<const DisplayDevice>& displayDevice);
+
+    // callIntoHwc exists so we can update our local state and call
+    // acceptDisplayChanges without unnecessarily updating the device's state
+    void setCompositionType(int32_t hwcId, HWC2::Composition type,
+            bool callIntoHwc = true);
+    HWC2::Composition getCompositionType(int32_t hwcId) const;
+
+    void setClearClientTarget(int32_t hwcId, bool clear);
+    bool getClearClientTarget(int32_t hwcId) const;
+
+    void updateCursorPosition(const sp<const DisplayDevice>& hw);
+#else
     void setGeometry(const sp<const DisplayDevice>& hw,
             HWComposer::HWCLayerInterface& layer);
     void setPerFrameData(const sp<const DisplayDevice>& hw,
@@ -210,12 +253,17 @@
             HWComposer::HWCLayerInterface& layer);
 
     Rect getPosition(const sp<const DisplayDevice>& hw);
+#endif
 
     /*
      * called after page-flip
      */
+#ifdef USE_HWC2
+    void onLayerDisplayed(const sp<Fence>& releaseFence);
+#else
     void onLayerDisplayed(const sp<const DisplayDevice>& hw,
             HWComposer::HWCLayerInterface* layer);
+#endif
 
     bool shouldPresentNow(const DispSync& dispSync) const;
 
@@ -230,6 +278,11 @@
      */
     void onPostComposition();
 
+#ifdef USE_HWC2
+    // If a buffer was replaced this frame, release the former buffer
+    void releasePendingBuffer();
+#endif
+
     /*
      * draw - performs some global clipping optimizations
      * and calls onDraw().
@@ -294,8 +347,40 @@
     /*
      * Returns if a frame is queued.
      */
-    bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }
+    bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
+            mSidebandStreamChanged || mAutoRefresh; }
 
+#ifdef USE_HWC2
+    // -----------------------------------------------------------------------
+
+    bool hasHwcLayer(int32_t hwcId) {
+        if (mHwcLayers.count(hwcId) == 0) {
+            return false;
+        }
+        if (mHwcLayers[hwcId].layer->isAbandoned()) {
+            ALOGI("Erasing abandoned layer %s on %d", mName.string(), hwcId);
+            mHwcLayers.erase(hwcId);
+            return false;
+        }
+        return true;
+    }
+
+    std::shared_ptr<HWC2::Layer> getHwcLayer(int32_t hwcId) {
+        if (mHwcLayers.count(hwcId) == 0) {
+            return nullptr;
+        }
+        return mHwcLayers[hwcId].layer;
+    }
+
+    void setHwcLayer(int32_t hwcId, std::shared_ptr<HWC2::Layer>&& layer) {
+        if (layer) {
+            mHwcLayers[hwcId].layer = layer;
+        } else {
+            mHwcLayers.erase(hwcId);
+        }
+    }
+
+#endif
     // -----------------------------------------------------------------------
 
     void clearWithOpenGL(const sp<const DisplayDevice>& hw, const Region& clip) const;
@@ -317,6 +402,10 @@
     void logFrameStats();
     void getFrameStats(FrameStats* outStats) const;
 
+    void getFenceData(String8* outName, uint64_t* outFrameNumber,
+            bool* outIsGlesComposition, nsecs_t* outPostedTime,
+            sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const;
+
 protected:
     // constant
     sp<SurfaceFlinger> mFlinger;
@@ -343,7 +432,7 @@
     virtual void onFrameReplaced(const BufferItem& item) override;
     virtual void onSidebandStreamChanged() override;
 
-    void commitTransaction();
+    void commitTransaction(const State& stateToCommit);
 
     // needsLinearFiltering - true if this surface's state requires filtering
     bool needsFiltering(const sp<const DisplayDevice>& hw) const;
@@ -362,6 +451,66 @@
     // Temporary - Used only for LEGACY camera mode.
     uint32_t getProducerStickyTransform() const;
 
+    // -----------------------------------------------------------------------
+
+    class SyncPoint
+    {
+    public:
+        SyncPoint(uint64_t frameNumber) : mFrameNumber(frameNumber),
+                mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+
+        uint64_t getFrameNumber() const {
+            return mFrameNumber;
+        }
+
+        bool frameIsAvailable() const {
+            return mFrameIsAvailable;
+        }
+
+        void setFrameAvailable() {
+            mFrameIsAvailable = true;
+        }
+
+        bool transactionIsApplied() const {
+            return mTransactionIsApplied;
+        }
+
+        void setTransactionApplied() {
+            mTransactionIsApplied = true;
+        }
+
+    private:
+        const uint64_t mFrameNumber;
+        std::atomic<bool> mFrameIsAvailable;
+        std::atomic<bool> mTransactionIsApplied;
+    };
+
+    // SyncPoints which will be signaled when the correct frame is at the head
+    // of the queue and dropped after the frame has been latched. Protected by
+    // mLocalSyncPointMutex.
+    Mutex mLocalSyncPointMutex;
+    std::list<std::shared_ptr<SyncPoint>> mLocalSyncPoints;
+
+    // SyncPoints which will be signaled and then dropped when the transaction
+    // is applied
+    std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints;
+
+    uint64_t getHeadFrameNumber() const;
+
+    // Returns false if the relevant frame has already been latched
+    bool addSyncPoint(const std::shared_ptr<SyncPoint>& point);
+
+    void pushPendingState();
+    void popPendingState(State* stateToCommit);
+    bool applyPendingStates(State* stateToCommit);
+
+    // Returns mCurrentScaling mode (originating from the
+    // Client) or mOverrideScalingMode mode (originating from
+    // the Surface Controller) if set.
+    uint32_t getEffectiveScalingMode() const;
+public:
+    void notifyAvailableFrames();
+private:
 
     // -----------------------------------------------------------------------
 
@@ -378,6 +527,10 @@
     State mDrawingState;
     volatile int32_t mTransactionFlags;
 
+    // Accessed from main thread and binder threads
+    Mutex mPendingStateMutex;
+    Vector<State> mPendingStates;
+
     // thread-safe
     volatile int32_t mQueuedFrames;
     volatile int32_t mSidebandStreamChanged; // used like an atomic boolean
@@ -389,7 +542,10 @@
     Rect mCurrentCrop;
     uint32_t mCurrentTransform;
     uint32_t mCurrentScalingMode;
+    // We encode unset as -1.
+    int32_t mOverrideScalingMode;
     bool mCurrentOpacity;
+    std::atomic<uint64_t> mCurrentFrameNumber;
     bool mRefreshPending;
     bool mFrameLatencyNeeded;
     // Whether filtering is forced on or not
@@ -401,6 +557,25 @@
     // The texture used to draw the layer in GLES composition mode
     mutable Texture mTexture;
 
+#ifdef USE_HWC2
+    // HWC items, accessed from the main thread
+    struct HWCInfo {
+        HWCInfo()
+          : layer(),
+            forceClientComposition(false),
+            compositionType(HWC2::Composition::Invalid),
+            clearClientTarget(false) {}
+
+        std::shared_ptr<HWC2::Layer> layer;
+        bool forceClientComposition;
+        HWC2::Composition compositionType;
+        bool clearClientTarget;
+    };
+    std::unordered_map<int32_t, HWCInfo> mHwcLayers;
+#else
+    bool mIsGlesComposition;
+#endif
+
     // page-flip thread (currently main thread)
     bool mProtectedByApp; // application requires protected path to external sink
 
@@ -417,8 +592,10 @@
     mutable Mutex mQueueItemLock;
     Condition mQueueItemCondition;
     Vector<BufferItem> mQueueItems;
-    uint64_t mLastFrameNumberReceived;
+    std::atomic<uint64_t> mLastFrameNumberReceived;
     bool mUpdateTexImageFailed; // This is only modified from the main thread
+
+    bool mAutoRefresh;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index 14aa328..4d5b3db 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -14,6 +14,10 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "LayerDim"
+
 #include <stdlib.h>
 #include <stdint.h>
 #include <sys/types.h>
diff --git a/services/surfaceflinger/MessageQueue.cpp b/services/surfaceflinger/MessageQueue.cpp
index 1ad86a6..99efd39 100644
--- a/services/surfaceflinger/MessageQueue.cpp
+++ b/services/surfaceflinger/MessageQueue.cpp
@@ -119,6 +119,7 @@
                 continue;
             case Looper::POLL_ERROR:
                 ALOGE("Looper::POLL_ERROR");
+                continue;
             case Looper::POLL_TIMEOUT:
                 // timeout (should not happen)
                 continue;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index fb7af97..faab62c 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -56,13 +56,18 @@
     return mProducer->requestBuffer(slot, buf);
 }
 
-status_t MonitoredProducer::setBufferCount(int bufferCount) {
-    return mProducer->setBufferCount(bufferCount);
+status_t MonitoredProducer::setMaxDequeuedBufferCount(
+        int maxDequeuedBuffers) {
+    return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
+}
+
+status_t MonitoredProducer::setAsyncMode(bool async) {
+    return mProducer->setAsyncMode(async);
 }
 
 status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence,
-        bool async, uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
-    return mProducer->dequeueBuffer(slot, fence, async, w, h, format, usage);
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t usage) {
+    return mProducer->dequeueBuffer(slot, fence, w, h, format, usage);
 }
 
 status_t MonitoredProducer::detachBuffer(int slot) {
@@ -84,8 +89,8 @@
     return mProducer->queueBuffer(slot, input, output);
 }
 
-void MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
-    mProducer->cancelBuffer(slot, fence);
+status_t MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
+    return mProducer->cancelBuffer(slot, fence);
 }
 
 int MonitoredProducer::query(int what, int* value) {
@@ -105,9 +110,9 @@
     return mProducer->setSidebandStream(stream);
 }
 
-void MonitoredProducer::allocateBuffers(bool async, uint32_t width,
-        uint32_t height, PixelFormat format, uint32_t usage) {
-    mProducer->allocateBuffers(async, width, height, format, usage);
+void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
+        PixelFormat format, uint32_t usage) {
+    mProducer->allocateBuffers(width, height, format, usage);
 }
 
 status_t MonitoredProducer::allowAllocation(bool allow) {
@@ -122,6 +127,28 @@
     return mProducer->getConsumerName();
 }
 
+uint64_t MonitoredProducer::getNextFrameNumber() const {
+    return mProducer->getNextFrameNumber();
+}
+
+status_t MonitoredProducer::setSharedBufferMode(bool sharedBufferMode) {
+    return mProducer->setSharedBufferMode(sharedBufferMode);
+}
+
+status_t MonitoredProducer::setAutoRefresh(bool autoRefresh) {
+    return mProducer->setAutoRefresh(autoRefresh);
+}
+
+status_t MonitoredProducer::setDequeueTimeout(nsecs_t timeout) {
+    return mProducer->setDequeueTimeout(timeout);
+}
+
+status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+        sp<Fence>* outFence, float outTransformMatrix[16]) {
+    return mProducer->getLastQueuedBuffer(outBuffer, outFence,
+            outTransformMatrix);
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return IInterface::asBinder(mProducer).get();
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index da95766..ce756dc 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -35,9 +35,10 @@
 
     // From IGraphicBufferProducer
     virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
-    virtual status_t setBufferCount(int bufferCount);
-    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, bool async,
-            uint32_t w, uint32_t h, PixelFormat format, uint32_t usage);
+    virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
+    virtual status_t setAsyncMode(bool async);
+    virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w,
+            uint32_t h, PixelFormat format, uint32_t usage);
     virtual status_t detachBuffer(int slot);
     virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence);
@@ -45,18 +46,24 @@
             const sp<GraphicBuffer>& buffer);
     virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
             QueueBufferOutput* output);
-    virtual void cancelBuffer(int slot, const sp<Fence>& fence);
+    virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
     virtual int query(int what, int* value);
     virtual status_t connect(const sp<IProducerListener>& token, int api,
             bool producerControlledByApp, QueueBufferOutput* output);
     virtual status_t disconnect(int api);
     virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
-    virtual void allocateBuffers(bool async, uint32_t width, uint32_t height,
+    virtual void allocateBuffers(uint32_t width, uint32_t height,
             PixelFormat format, uint32_t usage);
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
+    virtual uint64_t getNextFrameNumber() const override;
+    virtual status_t setDequeueTimeout(nsecs_t timeout) override;
+    virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
+            sp<Fence>* outFence, float outTransformMatrix[16]) override;
     virtual IBinder* onAsBinder();
+    virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
+    virtual status_t setAutoRefresh(bool autoRefresh) override;
 
 private:
     sp<IGraphicBufferProducer> mProducer;
diff --git a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp
index 9a47568..579affb 100644
--- a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.cpp
@@ -28,13 +28,25 @@
 }
 
 void GLES10RenderEngine::setupLayerBlending(
+#ifdef USE_HWC2
+    bool premultipliedAlpha, bool opaque, float alpha) {
+#else
     bool premultipliedAlpha, bool opaque, int alpha) {
+#endif
     // OpenGL ES 1.0 doesn't support texture combiners.
     // This path doesn't properly handle opaque layers that have non-opaque
     // alpha values. The alpha channel will be copied into the framebuffer or
     // screenshot, so if the framebuffer or screenshot is blended on top of
     // something else,  whatever is below the window will incorrectly show
     // through.
+#ifdef USE_HWC2
+    if (CC_UNLIKELY(alpha < 1.0f)) {
+        if (premultipliedAlpha) {
+            glColor4f(alpha, alpha, alpha, alpha);
+        } else {
+            glColor4f(1.0f, 1.0f, 1.0f, alpha);
+        }
+#else
     if (CC_UNLIKELY(alpha < 0xFF)) {
         GLfloat floatAlpha = alpha * (1.0f / 255.0f);
         if (premultipliedAlpha) {
@@ -42,12 +54,17 @@
         } else {
             glColor4f(1.0f, 1.0f, 1.0f, floatAlpha);
         }
+#endif
         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
     } else {
         glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
     }
 
+#ifdef USE_HWC2
+    if (alpha < 1.0f || !opaque) {
+#else
     if (alpha < 0xFF || !opaque) {
+#endif
         glEnable(GL_BLEND);
         glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
                     GL_ONE_MINUS_SRC_ALPHA);
diff --git a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h
index f9c7c04..61abd6a 100644
--- a/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES10RenderEngine.h
@@ -30,7 +30,12 @@
 class GLES10RenderEngine : public GLES11RenderEngine {
     virtual ~GLES10RenderEngine();
 protected:
+#ifdef USE_HWC2
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
+            float alpha) override;
+#else
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
+#endif
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
index 1a9f59b..847cdb3 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.cpp
@@ -107,20 +107,33 @@
     glMatrixMode(GL_MODELVIEW);
 }
 
+#ifdef USE_HWC2
+void GLES11RenderEngine::setupLayerBlending(bool premultipliedAlpha,
+        bool opaque, float alpha) {
+#else
 void GLES11RenderEngine::setupLayerBlending(
     bool premultipliedAlpha, bool opaque, int alpha) {
+#endif
     GLenum combineRGB;
     GLenum combineAlpha;
     GLenum src0Alpha;
     GLfloat envColor[4];
 
+#ifdef USE_HWC2
+    if (CC_UNLIKELY(alpha < 1.0f)) {
+#else
     if (CC_UNLIKELY(alpha < 0xFF)) {
+#endif
         // Cv = premultiplied ? Cs*alpha : Cs
         // Av = !opaque       ? As*alpha : As
         combineRGB   = premultipliedAlpha ? GL_MODULATE : GL_REPLACE;
         combineAlpha = !opaque            ? GL_MODULATE : GL_REPLACE;
         src0Alpha    = GL_CONSTANT;
+#ifdef USE_HWC2
+        envColor[0]  = alpha;
+#else
         envColor[0]  = alpha * (1.0f / 255.0f);
+#endif
     } else {
         // Cv = Cs
         // Av = opaque ? 1.0 : As
@@ -152,7 +165,11 @@
         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, envColor);
     }
 
+#ifdef USE_HWC2
+    if (alpha < 1.0f || !opaque) {
+#else
     if (alpha < 0xFF || !opaque) {
+#endif
         glEnable(GL_BLEND);
         glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA,
                     GL_ONE_MINUS_SRC_ALPHA);
@@ -161,16 +178,28 @@
     }
 }
 
+#ifdef USE_HWC2
+void GLES11RenderEngine::setupDimLayerBlending(float alpha) {
+#else
 void GLES11RenderEngine::setupDimLayerBlending(int alpha) {
+#endif
     glDisable(GL_TEXTURE_EXTERNAL_OES);
     glDisable(GL_TEXTURE_2D);
+#ifdef USE_HWC2
+    if (alpha == 1.0f) {
+#else
     if (alpha == 0xFF) {
+#endif
         glDisable(GL_BLEND);
     } else {
         glEnable(GL_BLEND);
         glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
     }
+#ifdef USE_HWC2
+    glColor4f(0, 0, 0, alpha);
+#else
     glColor4f(0, 0, 0, alpha/255.0f);
+#endif
 }
 
 void GLES11RenderEngine::setupLayerTexturing(const Texture& texture) {
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 08de646..4cd968d 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -51,9 +51,17 @@
 
     virtual void dump(String8& result);
     virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation);
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
+            Rect sourceCrop, size_t hwh, bool yswap,
+            Transform::orientation_flags rotation);
+#ifdef USE_HWC2
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
+            float alpha) override;
+    virtual void setupDimLayerBlending(float alpha) override;
+#else
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
+            int alpha);
     virtual void setupDimLayerBlending(int alpha);
+#endif
     virtual void setupLayerTexturing(const Texture& texture);
     virtual void setupLayerBlackedOut();
     virtual void setupFillWithColor(float r, float g, float b, float a) ;
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 1fabaf5..406e611 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -117,14 +117,25 @@
     mVpHeight = vph;
 }
 
+#ifdef USE_HWC2
+void GLES20RenderEngine::setupLayerBlending(bool premultipliedAlpha,
+        bool opaque, float alpha) {
+#else
 void GLES20RenderEngine::setupLayerBlending(
     bool premultipliedAlpha, bool opaque, int alpha) {
+#endif
 
     mState.setPremultipliedAlpha(premultipliedAlpha);
     mState.setOpaque(opaque);
+#ifdef USE_HWC2
+    mState.setPlaneAlpha(alpha);
+
+    if (alpha < 1.0f || !opaque) {
+#else
     mState.setPlaneAlpha(alpha / 255.0f);
 
     if (alpha < 0xFF || !opaque) {
+#endif
         glEnable(GL_BLEND);
         glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     } else {
@@ -132,14 +143,26 @@
     }
 }
 
+#ifdef USE_HWC2
+void GLES20RenderEngine::setupDimLayerBlending(float alpha) {
+#else
 void GLES20RenderEngine::setupDimLayerBlending(int alpha) {
+#endif
     mState.setPlaneAlpha(1.0f);
     mState.setPremultipliedAlpha(true);
     mState.setOpaque(false);
+#ifdef USE_HWC2
+    mState.setColor(0, 0, 0, alpha);
+#else
     mState.setColor(0, 0, 0, alpha/255.0f);
+#endif
     mState.disableTexture();
 
+#ifdef USE_HWC2
+    if (alpha == 1.0f) {
+#else
     if (alpha == 0xFF) {
+#endif
         glDisable(GL_BLEND);
     } else {
         glEnable(GL_BLEND);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 819356a..7c3f9b5 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -66,9 +66,17 @@
 
     virtual void dump(String8& result);
     virtual void setViewportAndProjection(size_t vpw, size_t vph,
-            Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation);
-    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha);
+            Rect sourceCrop, size_t hwh, bool yswap,
+            Transform::orientation_flags rotation);
+#ifdef USE_HWC2
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
+            float alpha) override;
+    virtual void setupDimLayerBlending(float alpha) override;
+#else
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque,
+            int alpha);
     virtual void setupDimLayerBlending(int alpha);
+#endif
     virtual void setupLayerTexturing(const Texture& texture);
     virtual void setupLayerBlackedOut();
     virtual void setupFillWithColor(float r, float g, float b, float a);
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 7cd42e4..27357b9 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -148,7 +148,7 @@
     return engine;
 }
 
-RenderEngine::RenderEngine() : mEGLContext(EGL_NO_CONTEXT) {
+RenderEngine::RenderEngine() : mEGLConfig(NULL), mEGLContext(EGL_NO_CONTEXT) {
 }
 
 RenderEngine::~RenderEngine() {
@@ -316,7 +316,7 @@
     friend class Adder;
     KeyedVector<Attribute, EGLint> mList;
     struct Attribute {
-        Attribute() {};
+        Attribute() : v(0) {};
         Attribute(EGLint v) : v(v) { }
         EGLint v;
         bool operator < (const Attribute& other) const {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index 31a961e..9cc1ed7 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -93,8 +93,13 @@
     virtual void checkErrors() const;
     virtual void setViewportAndProjection(size_t vpw, size_t vph,
             Rect sourceCrop, size_t hwh, bool yswap, Transform::orientation_flags rotation) = 0;
+#ifdef USE_HWC2
+    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, float alpha) = 0;
+    virtual void setupDimLayerBlending(float alpha) = 0;
+#else
     virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, int alpha) = 0;
     virtual void setupDimLayerBlending(int alpha) = 0;
+#endif
     virtual void setupLayerTexturing(const Texture& texture) = 0;
     virtual void setupLayerBlackedOut() = 0;
     virtual void setupFillWithColor(float r, float g, float b, float a) = 0;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fdc3650..a69b11b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+// #define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
 #include <stdint.h>
@@ -52,6 +53,7 @@
 #include <utils/String8.h>
 #include <utils/String16.h>
 #include <utils/StopWatch.h>
+#include <utils/Timers.h>
 #include <utils/Trace.h>
 
 #include <private/android_filesystem_config.h>
@@ -133,8 +135,9 @@
         mRepaintEverything(0),
         mRenderEngine(NULL),
         mBootTime(systemTime()),
+        mBuiltinDisplays(),
         mVisibleRegionsDirty(false),
-        mHwWorkListDirty(false),
+        mGeometryInvalid(false),
         mAnimCompositionPending(false),
         mDebugRegion(0),
         mDebugDDMS(0),
@@ -146,6 +149,7 @@
         mLastTransactionTime(0),
         mBootFinished(false),
         mForceFullDamage(false),
+        mPrimaryDispSync("PrimaryDispSync"),
         mPrimaryHWVsyncEnabled(false),
         mHWVsyncAvailable(false),
         mDaltonize(false),
@@ -235,9 +239,8 @@
     sp<BBinder> token = new DisplayToken(this);
 
     Mutex::Autolock _l(mStateLock);
-    DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL);
+    DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
     info.displayName = displayName;
-    info.isSecure = secure;
     mCurrentState.displays.add(token, info);
 
     return token;
@@ -263,12 +266,12 @@
 }
 
 void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
+    ALOGV("createBuiltinDisplayLocked(%d)", type);
     ALOGW_IF(mBuiltinDisplays[type],
             "Overwriting display token for display type %d", type);
     mBuiltinDisplays[type] = new BBinder();
-    DisplayDeviceState info(type);
     // All non-virtual displays are currently considered secure.
-    info.isSecure = true;
+    DisplayDeviceState info(type, true);
     mCurrentState.displays.add(mBuiltinDisplays[type], info);
 }
 
@@ -304,6 +307,10 @@
     // formerly we would just kill the process, but we now ask it to exit so it
     // can choose where to stop the animation.
     property_set("service.bootanim.exit", "1");
+
+    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
+    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
+                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
 }
 
 void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
@@ -325,11 +332,12 @@
 class DispSyncSource : public VSyncSource, private DispSync::Callback {
 public:
     DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
-        const char* label) :
+        const char* name) :
+            mName(name),
             mValue(0),
             mTraceVsync(traceVsync),
-            mVsyncOnLabel(String8::format("VsyncOn-%s", label)),
-            mVsyncEventLabel(String8::format("VSYNC-%s", label)),
+            mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+            mVsyncEventLabel(String8::format("VSYNC-%s", name)),
             mDispSync(dispSync),
             mCallbackMutex(),
             mCallback(),
@@ -342,7 +350,7 @@
     virtual void setVSyncEnabled(bool enable) {
         Mutex::Autolock lock(mVsyncMutex);
         if (enable) {
-            status_t err = mDispSync->addEventListener(mPhaseOffset,
+            status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
                     static_cast<DispSync::Callback*>(this));
             if (err != NO_ERROR) {
                 ALOGE("error registering vsync callback: %s (%d)",
@@ -393,7 +401,7 @@
         }
 
         // Add a listener with the new offset
-        err = mDispSync->addEventListener(mPhaseOffset,
+        err = mDispSync->addEventListener(mName, mPhaseOffset,
                 static_cast<DispSync::Callback*>(this));
         if (err != NO_ERROR) {
             ALOGE("error registering vsync callback: %s (%d)",
@@ -419,6 +427,8 @@
         }
     }
 
+    const char* const mName;
+
     int mValue;
 
     const bool mTraceVsync;
@@ -439,80 +449,48 @@
     ALOGI(  "SurfaceFlinger's main thread ready to run. "
             "Initializing graphics H/W...");
 
+    { // Autolock scope
+        Mutex::Autolock _l(mStateLock);
+
+        // initialize EGL for the default display
+        mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        eglInitialize(mEGLDisplay, NULL, NULL);
+
+        // start the EventThread
+        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+                vsyncPhaseOffsetNs, true, "app");
+        mEventThread = new EventThread(vsyncSrc, *this);
+        sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+                sfVsyncPhaseOffsetNs, true, "sf");
+        mSFEventThread = new EventThread(sfVsyncSrc, *this);
+        mEventQueue.setEventThread(mSFEventThread);
+
+        // Get a RenderEngine for the given display / config (can't fail)
+        mRenderEngine = RenderEngine::create(mEGLDisplay,
+                HAL_PIXEL_FORMAT_RGBA_8888);
+    }
+
+    // Drop the state lock while we initialize the hardware composer. We drop
+    // the lock because on creation, it will call back into SurfaceFlinger to
+    // initialize the primary display.
+    mHwc = new HWComposer(this);
+    mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));
+
     Mutex::Autolock _l(mStateLock);
 
-    // initialize EGL for the default display
-    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    eglInitialize(mEGLDisplay, NULL, NULL);
-
-    // start the EventThread
-    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-            vsyncPhaseOffsetNs, true, "app");
-    mEventThread = new EventThread(vsyncSrc);
-    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
-            sfVsyncPhaseOffsetNs, true, "sf");
-    mSFEventThread = new EventThread(sfVsyncSrc);
-    mEventQueue.setEventThread(mSFEventThread);
-
-    // Initialize the H/W composer object.  There may or may not be an
-    // actual hardware composer underneath.
-    mHwc = new HWComposer(this,
-            *static_cast<HWComposer::EventHandler *>(this));
-
-    // get a RenderEngine for the given display / config (can't fail)
-    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
-
     // retrieve the EGL context that was selected/created
     mEGLContext = mRenderEngine->getEGLContext();
 
     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
             "couldn't create EGLContext");
 
-    // initialize our non-virtual displays
-    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
-        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
-        // set-up the displays that are already connected
-        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
-            // All non-virtual displays are currently considered secure.
-            bool isSecure = true;
-            createBuiltinDisplayLocked(type);
-            wp<IBinder> token = mBuiltinDisplays[i];
-
-            sp<IGraphicBufferProducer> producer;
-            sp<IGraphicBufferConsumer> consumer;
-            BufferQueue::createBufferQueue(&producer, &consumer,
-                    new GraphicBufferAlloc());
-
-            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
-                    consumer);
-            int32_t hwcId = allocateHwcDisplayId(type);
-            sp<DisplayDevice> hw = new DisplayDevice(this,
-                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
-                    fbs, producer,
-                    mRenderEngine->getEGLConfig());
-            if (i > DisplayDevice::DISPLAY_PRIMARY) {
-                // FIXME: currently we don't get blank/unblank requests
-                // for displays other than the main display, so we always
-                // assume a connected display is unblanked.
-                ALOGD("marking display %zu as acquired/unblanked", i);
-                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
-            }
-            mDisplays.add(token, hw);
-        }
-    }
-
-    // make the GLContext current so that we can create textures when creating Layers
-    // (which may happens before we render something)
+    // make the GLContext current so that we can create textures when creating
+    // Layers (which may happens before we render something)
     getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
 
     mEventControlThread = new EventControlThread(this);
     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
 
-    // set a fake vsync period if there is no HWComposer
-    if (mHwc->initCheck() != NO_ERROR) {
-        mPrimaryDispSync.setPeriod(16666667);
-    }
-
     // initialize our drawing state
     mDrawingState = mCurrentState;
 
@@ -521,11 +499,8 @@
 
     // start boot animation
     startBootAnim();
-}
 
-int32_t SurfaceFlinger::allocateHwcDisplayId(DisplayDevice::DisplayType type) {
-    return (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) ?
-            type : mHwc->allocateDisplayId();
+    ALOGV("Done initializing");
 }
 
 void SurfaceFlinger::startBootAnim() {
@@ -591,14 +566,11 @@
 
     configs->clear();
 
-    const Vector<HWComposer::DisplayConfig>& hwConfigs =
-            getHwComposer().getConfigs(type);
-    for (size_t c = 0; c < hwConfigs.size(); ++c) {
-        const HWComposer::DisplayConfig& hwConfig = hwConfigs[c];
+    for (const auto& hwConfig : getHwComposer().getConfigs(type)) {
         DisplayInfo info = DisplayInfo();
 
-        float xdpi = hwConfig.xdpi;
-        float ydpi = hwConfig.ydpi;
+        float xdpi = hwConfig->getDpiX();
+        float ydpi = hwConfig->getDpiY();
 
         if (type == DisplayDevice::DISPLAY_PRIMARY) {
             // The density of the device is provided by a build property
@@ -626,13 +598,15 @@
             info.orientation = 0;
         }
 
-        info.w = hwConfig.width;
-        info.h = hwConfig.height;
+        info.w = hwConfig->getWidth();
+        info.h = hwConfig->getHeight();
         info.xdpi = xdpi;
         info.ydpi = ydpi;
-        info.fps = float(1e9 / hwConfig.refresh);
+        info.fps = 1e9 / hwConfig->getVsyncPeriod();
         info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
-        info.colorTransform = hwConfig.colorTransform;
+
+        // TODO: Hook this back up
+        info.colorTransform = 0;
 
         // This is how far in advance a buffer must be queued for
         // presentation at a given time.  If you want a buffer to appear
@@ -646,8 +620,8 @@
         //
         // We add an additional 1ms to allow for processing time and
         // differences between the ideal and actual refresh rate.
-        info.presentationDeadline =
-                hwConfig.refresh - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
+        info.presentationDeadline = hwConfig->getVsyncPeriod() -
+                SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
 
         // All non-virtual displays are currently considered secure.
         info.secure = true;
@@ -745,6 +719,27 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& display,
+        HdrCapabilities* outCapabilities) const {
+    Mutex::Autolock _l(mStateLock);
+
+    sp<const DisplayDevice> displayDevice(getDisplayDevice(display));
+    if (displayDevice == nullptr) {
+        ALOGE("getHdrCapabilities: Invalid display %p", displayDevice.get());
+        return BAD_VALUE;
+    }
+
+    std::unique_ptr<HdrCapabilities> capabilities =
+            mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
+    if (capabilities) {
+        std::swap(*outCapabilities, *capabilities);
+    } else {
+        return BAD_VALUE;
+    }
+
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
@@ -805,12 +800,13 @@
     if (makeAvailable) {
         mHWVsyncAvailable = true;
     } else if (!mHWVsyncAvailable) {
-        ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
+        // Hardware vsync is not currently available, so abort the resync
+        // attempt for now
         return;
     }
 
-    const nsecs_t period =
-            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+    const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const nsecs_t period = activeConfig->getVsyncPeriod();
 
     mPrimaryDispSync.reset();
     mPrimaryDispSync.setPeriod(period);
@@ -836,7 +832,14 @@
     }
 }
 
-void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
+void SurfaceFlinger::resyncWithRateLimit() {
+    static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+    if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+        resyncToHardwareVsync(false);
+    }
+}
+
+void SurfaceFlinger::onVSyncReceived(int32_t type, nsecs_t timestamp) {
     bool needsHwVsync = false;
 
     { // Scope for the lock
@@ -853,19 +856,34 @@
     }
 }
 
-void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
-    if (mEventThread == NULL) {
-        // This is a temporary workaround for b/7145521.  A non-null pointer
-        // does not mean EventThread has finished initializing, so this
-        // is not a correct fix.
-        ALOGW("WARNING: EventThread not started, ignoring hotplug");
-        return;
-    }
+void SurfaceFlinger::onHotplugReceived(int32_t disp, bool connected) {
+    ALOGV("onHotplugReceived(%d, %s)", disp, connected ? "true" : "false");
+    if (disp == DisplayDevice::DISPLAY_PRIMARY) {
+        Mutex::Autolock lock(mStateLock);
 
-    if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        // All non-virtual displays are currently considered secure.
+        bool isSecure = true;
+
+        int32_t type = DisplayDevice::DISPLAY_PRIMARY;
+        createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
+        wp<IBinder> token = mBuiltinDisplays[type];
+
+        sp<IGraphicBufferProducer> producer;
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer,
+                new GraphicBufferAlloc());
+
+        sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc,
+                DisplayDevice::DISPLAY_PRIMARY, consumer);
+        sp<DisplayDevice> hw = new DisplayDevice(this,
+                DisplayDevice::DISPLAY_PRIMARY, disp, isSecure, token, fbs,
+                producer, mRenderEngine->getEGLConfig());
+        mDisplays.add(token, hw);
+    } else {
+        auto type = DisplayDevice::DISPLAY_EXTERNAL;
         Mutex::Autolock _l(mStateLock);
         if (connected) {
-            createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
+            createBuiltinDisplayLocked(type);
         } else {
             mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
             mBuiltinDisplays[type].clear();
@@ -876,9 +894,10 @@
     }
 }
 
-void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
+void SurfaceFlinger::setVsyncEnabled(int disp, int enabled) {
     ATRACE_CALL();
-    getHwComposer().eventControl(disp, event, enabled);
+    getHwComposer().setVsyncEnabled(disp,
+            enabled ? HWC2::Vsync::Enable : HWC2::Vsync::Disable);
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what) {
@@ -924,6 +943,11 @@
 void SurfaceFlinger::handleMessageRefresh() {
     ATRACE_CALL();
 
+#ifdef ENABLE_FENCE_TRACKING
+    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+#else
+    nsecs_t refreshStartTime = 0;
+#endif
     static nsecs_t previousExpectedPresent = 0;
     nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
     static bool previousFrameMissed = false;
@@ -944,9 +968,15 @@
         setUpHWComposer();
         doDebugFlashRegions();
         doComposition();
-        postComposition();
+        postComposition(refreshStartTime);
     }
 
+    // Release any buffers which were replaced this frame
+    for (auto& layer : mLayersWithQueuedFrames) {
+        layer->releasePendingBuffer();
+    }
+    mLayersWithQueuedFrames.clear();
+
     previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
 }
 
@@ -971,7 +1001,6 @@
                 RenderEngine& engine(getRenderEngine());
                 engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
 
-                hw->compositionComplete();
                 hw->swapBuffers(getHwComposer());
             }
         }
@@ -983,15 +1012,18 @@
         usleep(mDebugRegion * 1000);
     }
 
-    HWComposer& hwc(getHwComposer());
-    if (hwc.initCheck() == NO_ERROR) {
-        status_t err = hwc.prepare();
-        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        status_t result = mDisplays[displayId]->prepareFrame(*mHwc);
+        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:"
+                " %d (%s)", displayId, result, strerror(-result));
     }
 }
 
 void SurfaceFlinger::preComposition()
 {
+    ATRACE_CALL();
+    ALOGV("preComposition");
+
     bool needExtraInvalidate = false;
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
@@ -1005,16 +1037,22 @@
     }
 }
 
-void SurfaceFlinger::postComposition()
+#ifdef ENABLE_FENCE_TRACKING
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+#else
+void SurfaceFlinger::postComposition(nsecs_t /*refreshStartTime*/)
+#endif
 {
+    ATRACE_CALL();
+    ALOGV("postComposition");
+
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
         layers[i]->onPostComposition();
     }
 
-    const HWComposer& hwc = getHwComposer();
-    sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
+    sp<Fence> presentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
 
     if (presentFence->isValid()) {
         if (mPrimaryDispSync.addPresentFence(presentFence)) {
@@ -1031,6 +1069,11 @@
         }
     }
 
+#ifdef ENABLE_FENCE_TRACKING
+    mFenceTracker.addFrame(refreshStartTime, presentFence,
+            hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
+#endif
+
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
@@ -1039,7 +1082,8 @@
         } else {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
-            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
+            nsecs_t presentTime =
+                    mHwc->getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
             mAnimFrameTracker.setActualPresentTime(presentTime);
         }
         mAnimFrameTracker.advanceFrame();
@@ -1067,6 +1111,9 @@
 }
 
 void SurfaceFlinger::rebuildLayerStacks() {
+    ATRACE_CALL();
+    ALOGV("rebuildLayerStacks");
+
     // rebuild the visible layer list per screen
     if (CC_UNLIKELY(mVisibleRegionsDirty)) {
         ATRACE_CALL();
@@ -1077,37 +1124,47 @@
         for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
             Region opaqueRegion;
             Region dirtyRegion;
-            Vector< sp<Layer> > layersSortedByZ;
-            const sp<DisplayDevice>& hw(mDisplays[dpy]);
-            const Transform& tr(hw->getTransform());
-            const Rect bounds(hw->getBounds());
-            if (hw->isDisplayOn()) {
+            Vector<sp<Layer>> layersSortedByZ;
+            const sp<DisplayDevice>& displayDevice(mDisplays[dpy]);
+            const Transform& tr(displayDevice->getTransform());
+            const Rect bounds(displayDevice->getBounds());
+            if (displayDevice->isDisplayOn()) {
                 SurfaceFlinger::computeVisibleRegions(layers,
-                        hw->getLayerStack(), dirtyRegion, opaqueRegion);
+                        displayDevice->getLayerStack(), dirtyRegion,
+                        opaqueRegion);
 
                 const size_t count = layers.size();
                 for (size_t i=0 ; i<count ; i++) {
                     const sp<Layer>& layer(layers[i]);
                     const Layer::State& s(layer->getDrawingState());
-                    if (s.layerStack == hw->getLayerStack()) {
+                    if (s.layerStack == displayDevice->getLayerStack()) {
                         Region drawRegion(tr.transform(
                                 layer->visibleNonTransparentRegion));
                         drawRegion.andSelf(bounds);
                         if (!drawRegion.isEmpty()) {
                             layersSortedByZ.add(layer);
+                        } else {
+                            // Clear out the HWC layer if this layer was
+                            // previously visible, but no longer is
+                            layer->setHwcLayer(displayDevice->getHwcDisplayId(),
+                                    nullptr);
                         }
                     }
                 }
             }
-            hw->setVisibleLayersSortedByZ(layersSortedByZ);
-            hw->undefinedRegion.set(bounds);
-            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
-            hw->dirtyRegion.orSelf(dirtyRegion);
+            displayDevice->setVisibleLayersSortedByZ(layersSortedByZ);
+            displayDevice->undefinedRegion.set(bounds);
+            displayDevice->undefinedRegion.subtractSelf(
+                    tr.transform(opaqueRegion));
+            displayDevice->dirtyRegion.orSelf(dirtyRegion);
         }
     }
 }
 
 void SurfaceFlinger::setUpHWComposer() {
+    ATRACE_CALL();
+    ALOGV("setUpHWComposer");
+
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
         bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
@@ -1137,86 +1194,61 @@
         }
     }
 
-    HWComposer& hwc(getHwComposer());
-    if (hwc.initCheck() == NO_ERROR) {
-        // build the h/w work list
-        if (CC_UNLIKELY(mHwWorkListDirty)) {
-            mHwWorkListDirty = false;
-            for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-                sp<const DisplayDevice> hw(mDisplays[dpy]);
-                const int32_t id = hw->getHwcDisplayId();
-                if (id >= 0) {
-                    const Vector< sp<Layer> >& currentLayers(
-                        hw->getVisibleLayersSortedByZ());
-                    const size_t count = currentLayers.size();
-                    if (hwc.createWorkList(id, count) == NO_ERROR) {
-                        HWComposer::LayerListIterator cur = hwc.begin(id);
-                        const HWComposer::LayerListIterator end = hwc.end(id);
-                        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                            const sp<Layer>& layer(currentLayers[i]);
-                            layer->setGeometry(hw, *cur);
-                            if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
-                                cur->setSkip(true);
-                            }
+    // build the h/w work list
+    if (CC_UNLIKELY(mGeometryInvalid)) {
+        mGeometryInvalid = false;
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            sp<const DisplayDevice> displayDevice(mDisplays[dpy]);
+            const auto hwcId = displayDevice->getHwcDisplayId();
+            if (hwcId >= 0) {
+                const Vector<sp<Layer>>& currentLayers(
+                        displayDevice->getVisibleLayersSortedByZ());
+                bool foundLayerWithoutHwc = false;
+                for (auto& layer : currentLayers) {
+                    if (!layer->hasHwcLayer(hwcId)) {
+                        auto hwcLayer = mHwc->createLayer(hwcId);
+                        if (hwcLayer) {
+                            layer->setHwcLayer(hwcId, std::move(hwcLayer));
+                        } else {
+                            layer->forceClientComposition(hwcId);
+                            foundLayerWithoutHwc = true;
+                            continue;
                         }
                     }
-                }
-            }
-        }
 
-        // set the per-frame data
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> hw(mDisplays[dpy]);
-            const int32_t id = hw->getHwcDisplayId();
-            if (id >= 0) {
-                const Vector< sp<Layer> >& currentLayers(
-                    hw->getVisibleLayersSortedByZ());
-                const size_t count = currentLayers.size();
-                HWComposer::LayerListIterator cur = hwc.begin(id);
-                const HWComposer::LayerListIterator end = hwc.end(id);
-                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                    /*
-                     * update the per-frame h/w composer data for each layer
-                     * and build the transparent region of the FB
-                     */
-                    const sp<Layer>& layer(currentLayers[i]);
-                    layer->setPerFrameData(hw, *cur);
-                }
-            }
-        }
-
-        // If possible, attempt to use the cursor overlay on each display.
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> hw(mDisplays[dpy]);
-            const int32_t id = hw->getHwcDisplayId();
-            if (id >= 0) {
-                const Vector< sp<Layer> >& currentLayers(
-                    hw->getVisibleLayersSortedByZ());
-                const size_t count = currentLayers.size();
-                HWComposer::LayerListIterator cur = hwc.begin(id);
-                const HWComposer::LayerListIterator end = hwc.end(id);
-                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-                    const sp<Layer>& layer(currentLayers[i]);
-                    if (layer->isPotentialCursor()) {
-                        cur->setIsCursorLayerHint();
-                        break;
+                    layer->setGeometry(displayDevice);
+                    if (mDebugDisableHWC || mDebugRegion || mDaltonize ||
+                            mHasColorMatrix) {
+                        layer->forceClientComposition(hwcId);
                     }
                 }
             }
         }
+    }
 
-        status_t err = hwc.prepare();
-        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
-
-        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-            sp<const DisplayDevice> hw(mDisplays[dpy]);
-            hw->prepareFrame(hwc);
+    // Set the per-frame data
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        auto& displayDevice = mDisplays[displayId];
+        const auto hwcId = displayDevice->getHwcDisplayId();
+        if (hwcId < 0) {
+            continue;
         }
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            layer->setPerFrameData(displayDevice);
+        }
+    }
+
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        status_t result = mDisplays[displayId]->prepareFrame(*mHwc);
+        ALOGE_IF(result != NO_ERROR, "prepareFrame for display %zd failed:"
+                " %d (%s)", displayId, result, strerror(-result));
     }
 }
 
 void SurfaceFlinger::doComposition() {
     ATRACE_CALL();
+    ALOGV("doComposition");
+
     const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
     for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
         const sp<DisplayDevice>& hw(mDisplays[dpy]);
@@ -1231,8 +1263,6 @@
             hw->flip(hw->swapRegion);
             hw->swapRegion.clear();
         }
-        // inform the h/w that we're done compositing
-        hw->compositionComplete();
     }
     postFramebuffer();
 }
@@ -1240,43 +1270,37 @@
 void SurfaceFlinger::postFramebuffer()
 {
     ATRACE_CALL();
+    ALOGV("postFramebuffer");
 
     const nsecs_t now = systemTime();
     mDebugInSwapBuffers = now;
 
-    HWComposer& hwc(getHwComposer());
-    if (hwc.initCheck() == NO_ERROR) {
-        if (!hwc.supportsFramebufferTarget()) {
-            // EGL spec says:
-            //   "surface must be bound to the calling thread's current context,
-            //    for the current rendering API."
-            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        auto& displayDevice = mDisplays[displayId];
+        const auto hwcId = displayDevice->getHwcDisplayId();
+        if (hwcId >= 0) {
+            mHwc->commit(hwcId);
         }
-        hwc.commit();
-    }
-
-    // make the default display current because the VirtualDisplayDevice code cannot
-    // deal with dequeueBuffer() being called outside of the composition loop; however
-    // the code below can call glFlush() which is allowed (and does in some case) call
-    // dequeueBuffer().
-    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
-
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        sp<const DisplayDevice> hw(mDisplays[dpy]);
-        const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
-        hw->onSwapBuffersCompleted(hwc);
-        const size_t count = currentLayers.size();
-        int32_t id = hw->getHwcDisplayId();
-        if (id >=0 && hwc.initCheck() == NO_ERROR) {
-            HWComposer::LayerListIterator cur = hwc.begin(id);
-            const HWComposer::LayerListIterator end = hwc.end(id);
-            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
-                currentLayers[i]->onLayerDisplayed(hw, &*cur);
+        displayDevice->onSwapBuffersCompleted();
+        if (displayId == 0) {
+            // Make the default display current because the VirtualDisplayDevice
+            // code cannot deal with dequeueBuffer() being called outside of the
+            // composition loop; however the code below can call glFlush() which
+            // is allowed to (and does in some case) call dequeueBuffer().
+            displayDevice->makeCurrent(mEGLDisplay, mEGLContext);
+        }
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            sp<Fence> releaseFence = Fence::NO_FENCE;
+            if (layer->getCompositionType(hwcId) == HWC2::Composition::Client) {
+                releaseFence = displayDevice->getClientTargetAcquireFence();
+            } else {
+                auto hwcLayer = layer->getHwcLayer(hwcId);
+                releaseFence = mHwc->getLayerReleaseFence(hwcId, hwcLayer);
             }
-        } else {
-            for (size_t i = 0; i < count; i++) {
-                currentLayers[i]->onLayerDisplayed(hw, NULL);
-            }
+            layer->onLayerDisplayed(releaseFence);
+        }
+        if (hwcId >= 0) {
+            mHwc->clearReleaseFences(hwcId);
         }
     }
 
@@ -1323,6 +1347,11 @@
     const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
 
+    // Notify all layers of available frames
+    for (size_t i = 0; i < count; ++i) {
+        currentLayers[i]->notifyAvailableFrames();
+    }
+
     /*
      * Traversal of the children
      * (perform the transaction for each of them if needed)
@@ -1431,7 +1460,7 @@
                     BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
                             new GraphicBufferAlloc());
 
-                    int32_t hwcDisplayId = -1;
+                    int32_t hwcId = -1;
                     if (state.isVirtualDisplay()) {
                         // Virtual displays without a surface are dormant:
                         // they have external state (layer stack, projection,
@@ -1448,15 +1477,14 @@
                                     NATIVE_WINDOW_HEIGHT, &height);
                             ALOGE_IF(status != NO_ERROR,
                                     "Unable to query height (%d)", status);
-                            if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
-                                    (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
-                                     height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
-                                hwcDisplayId = allocateHwcDisplayId(state.type);
-                            }
 
-                            sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
-                                    *mHwc, hwcDisplayId, state.surface,
-                                    bqProducer, bqConsumer, state.displayName);
+                            mHwc->allocateVirtualDisplay(width, height,
+                                    &hwcId);
+
+                            sp<VirtualDisplaySurface> vds =
+                                    new VirtualDisplaySurface(*mHwc,
+                                            hwcId, state.surface, bqProducer,
+                                            bqConsumer, state.displayName);
 
                             dispSurface = vds;
                             producer = vds;
@@ -1466,33 +1494,30 @@
                                 "adding a supported display, but rendering "
                                 "surface is provided (%p), ignoring it",
                                 state.surface.get());
-                        hwcDisplayId = allocateHwcDisplayId(state.type);
-                        // for supported (by hwc) displays we provide our
-                        // own rendering surface
-                        dispSurface = new FramebufferSurface(*mHwc, state.type,
-                                bqConsumer);
-                        producer = bqProducer;
+                        if (state.type == DisplayDevice::DISPLAY_EXTERNAL) {
+                            hwcId = DisplayDevice::DISPLAY_EXTERNAL;
+                            dispSurface = new FramebufferSurface(*mHwc,
+                                    DisplayDevice::DISPLAY_EXTERNAL,
+                                    bqConsumer);
+                            producer = bqProducer;
+                        } else {
+                            ALOGE("Attempted to add non-external non-virtual"
+                                    " display");
+                        }
                     }
 
                     const wp<IBinder>& display(curr.keyAt(i));
                     if (dispSurface != NULL) {
                         sp<DisplayDevice> hw = new DisplayDevice(this,
-                                state.type, hwcDisplayId,
-                                mHwc->getFormat(hwcDisplayId), state.isSecure,
-                                display, dispSurface, producer,
+                                state.type, hwcId, state.isSecure, display,
+                                dispSurface, producer,
                                 mRenderEngine->getEGLConfig());
                         hw->setLayerStack(state.layerStack);
                         hw->setProjection(state.orientation,
                                 state.viewport, state.frame);
                         hw->setDisplayName(state.displayName);
                         mDisplays.add(display, hw);
-                        if (state.isVirtualDisplay()) {
-                            if (hwcDisplayId >= 0) {
-                                mHwc->setVirtualDisplayProperties(hwcDisplayId,
-                                        hw->getWidth(), hw->getHeight(),
-                                        hw->getFormat());
-                            }
-                        } else {
+                        if (!state.isVirtualDisplay()) {
                             mEventThread->onHotplugReceived(state.type, true);
                         }
                     }
@@ -1585,7 +1610,7 @@
                 //       compute the actual visible region
                 // TODO: we could cache the transformed region
                 const Layer::State& s(layer->getDrawingState());
-                Region visibleReg = s.transform.transform(
+                Region visibleReg = s.active.transform.transform(
                         Region(Rect(s.active.w, s.active.h)));
                 invalidateLayerStack(s.layerStack, visibleReg);
             }
@@ -1599,26 +1624,14 @@
 
 void SurfaceFlinger::updateCursorAsync()
 {
-    HWComposer& hwc(getHwComposer());
-    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
-        sp<const DisplayDevice> hw(mDisplays[dpy]);
-        const int32_t id = hw->getHwcDisplayId();
-        if (id < 0) {
+    for (size_t displayId = 0; displayId < mDisplays.size(); ++displayId) {
+        auto& displayDevice = mDisplays[displayId];
+        if (displayDevice->getHwcDisplayId() < 0) {
             continue;
         }
-        const Vector< sp<Layer> >& currentLayers(
-            hw->getVisibleLayersSortedByZ());
-        const size_t count = currentLayers.size();
-        HWComposer::LayerListIterator cur = hwc.begin(id);
-        const HWComposer::LayerListIterator end = hwc.end(id);
-        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
-            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
-                continue;
-            }
-            const sp<Layer>& layer(currentLayers[i]);
-            Rect cursorPos = layer->getPosition(hw);
-            hwc.setCursorPositionAsync(id, cursorPos);
-            break;
+
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            layer->updateCursorPosition(displayDevice);
         }
     }
 }
@@ -1648,6 +1661,7 @@
         Region& outDirtyRegion, Region& outOpaqueRegion)
 {
     ATRACE_CALL();
+    ALOGV("computeVisibleRegions");
 
     Region aboveOpaqueLayers;
     Region aboveCoveredLayers;
@@ -1699,12 +1713,12 @@
         // handle hidden surfaces by setting the visible region to empty
         if (CC_LIKELY(layer->isVisible())) {
             const bool translucent = !layer->isOpaque(s);
-            Rect bounds(s.transform.transform(layer->computeBounds()));
+            Rect bounds(s.active.transform.transform(layer->computeBounds()));
             visibleRegion.set(bounds);
             if (!visibleRegion.isEmpty()) {
                 // Remove the transparent area from the visible region
                 if (translucent) {
-                    const Transform tr(s.transform);
+                    const Transform tr(s.active.transform);
                     if (tr.transformed()) {
                         if (tr.preserveRects()) {
                             // transform the transparent region
@@ -1720,8 +1734,8 @@
                 }
 
                 // compute the opaque region
-                const int32_t layerOrientation = s.transform.getOrientation();
-                if (s.alpha==255 && !translucent &&
+                const int32_t layerOrientation = s.active.transform.getOrientation();
+                if (s.alpha == 1.0f && !translucent &&
                         ((layerOrientation & Transform::ROT_INVALID) == false)) {
                     // the opaque region is the layer's footprint
                     opaqueRegion = visibleRegion;
@@ -1794,6 +1808,8 @@
 
 bool SurfaceFlinger::handlePageFlip()
 {
+    ALOGV("handlePageFlip");
+
     Region dirtyRegion;
 
     bool visibleRegions = false;
@@ -1809,13 +1825,12 @@
     // 3.) Layer 1 is latched.
     // Display is now waiting on Layer 1's frame, which is behind layer 0's
     // second frame. But layer 0's second frame could be waiting on display.
-    Vector<Layer*> layersWithQueuedFrames;
     for (size_t i = 0, count = layers.size(); i<count ; i++) {
         const sp<Layer>& layer(layers[i]);
         if (layer->hasQueuedFrame()) {
             frameQueued = true;
             if (layer->shouldPresentNow(mPrimaryDispSync)) {
-                layersWithQueuedFrames.push_back(layer.get());
+                mLayersWithQueuedFrames.push_back(layer.get());
             } else {
                 layer->useEmptyDamage();
             }
@@ -1823,8 +1838,7 @@
             layer->useEmptyDamage();
         }
     }
-    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
-        Layer* layer = layersWithQueuedFrames[i];
+    for (auto& layer : mLayersWithQueuedFrames) {
         const Region dirty(layer->latchBuffer(visibleRegions));
         layer->useSurfaceDamage();
         const Layer::State& s(layer->getDrawingState());
@@ -1836,17 +1850,17 @@
     // If we will need to wake up at some time in the future to deal with a
     // queued frame that shouldn't be displayed during this vsync period, wake
     // up during the next vsync period to check again.
-    if (frameQueued && layersWithQueuedFrames.empty()) {
+    if (frameQueued && mLayersWithQueuedFrames.empty()) {
         signalLayerUpdate();
     }
 
     // Only continue with the refresh if there is actually new work to do
-    return !layersWithQueuedFrames.empty();
+    return !mLayersWithQueuedFrames.empty();
 }
 
 void SurfaceFlinger::invalidateHwcGeometry()
 {
-    mHwWorkListDirty = true;
+    mGeometryInvalid = true;
 }
 
 
@@ -1859,9 +1873,12 @@
     // 2) There is work to be done (the dirty region isn't empty)
     bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
     if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
+        ALOGV("Skipping display composition");
         return;
     }
 
+    ALOGV("doDisplayComposition");
+
     Region dirtyRegion(inDirtyRegion);
 
     // compute the invalid region
@@ -1907,19 +1924,19 @@
     hw->swapBuffers(getHwComposer());
 }
 
-bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
+bool SurfaceFlinger::doComposeSurfaces(
+        const sp<const DisplayDevice>& displayDevice, const Region& dirty)
 {
-    RenderEngine& engine(getRenderEngine());
-    const int32_t id = hw->getHwcDisplayId();
-    HWComposer& hwc(getHwComposer());
-    HWComposer::LayerListIterator cur = hwc.begin(id);
-    const HWComposer::LayerListIterator end = hwc.end(id);
+    ALOGV("doComposeSurfaces");
 
-    bool hasGlesComposition = hwc.hasGlesComposition(id);
-    if (hasGlesComposition) {
-        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
+    const auto hwcId = displayDevice->getHwcDisplayId();
+    bool hasClientComposition = mHwc->hasClientComposition(hwcId);
+    if (hasClientComposition) {
+        ALOGV("hasClientComposition");
+
+        if (!displayDevice->makeCurrent(mEGLDisplay, mEGLContext)) {
             ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
-                  hw->getDisplayName().string());
+                  displayDevice->getDisplayName().string());
             eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
             if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
               ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
@@ -1928,25 +1945,25 @@
         }
 
         // Never touch the framebuffer if we don't have any framebuffer layers
-        const bool hasHwcComposition = hwc.hasHwcComposition(id);
-        if (hasHwcComposition) {
+        const bool hasDeviceComposition = mHwc->hasDeviceComposition(hwcId);
+        if (hasDeviceComposition) {
             // when using overlays, we assume a fully transparent framebuffer
             // NOTE: we could reduce how much we need to clear, for instance
             // remove where there are opaque FB layers. however, on some
             // GPUs doing a "clean slate" clear might be more efficient.
             // We'll revisit later if needed.
-            engine.clearWithColor(0, 0, 0, 0);
+            mRenderEngine->clearWithColor(0, 0, 0, 0);
         } else {
             // we start with the whole screen area
-            const Region bounds(hw->getBounds());
+            const Region bounds(displayDevice->getBounds());
 
             // we remove the scissor part
             // we're left with the letterbox region
             // (common case is that letterbox ends-up being empty)
-            const Region letterbox(bounds.subtract(hw->getScissor()));
+            const Region letterbox(bounds.subtract(displayDevice->getScissor()));
 
             // compute the area to clear
-            Region region(hw->undefinedRegion.merge(letterbox));
+            Region region(displayDevice->undefinedRegion.merge(letterbox));
 
             // but limit it to the dirty region
             region.andSelf(dirty);
@@ -1954,24 +1971,24 @@
             // screen is already cleared here
             if (!region.isEmpty()) {
                 // can happen with SurfaceView
-                drawWormhole(hw, region);
+                drawWormhole(displayDevice, region);
             }
         }
 
-        if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
+        if (displayDevice->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
             // just to be on the safe side, we don't set the
             // scissor on the main display. It should never be needed
             // anyways (though in theory it could since the API allows it).
-            const Rect& bounds(hw->getBounds());
-            const Rect& scissor(hw->getScissor());
+            const Rect& bounds(displayDevice->getBounds());
+            const Rect& scissor(displayDevice->getScissor());
             if (scissor != bounds) {
                 // scissor doesn't match the screen's dimensions, so we
                 // need to clear everything outside of it and enable
                 // the GL scissor so we don't draw anything where we shouldn't
 
                 // enable scissor for this frame
-                const uint32_t height = hw->getHeight();
-                engine.setScissor(scissor.left, height - scissor.bottom,
+                const uint32_t height = displayDevice->getHeight();
+                mRenderEngine->setScissor(scissor.left, height - scissor.bottom,
                         scissor.getWidth(), scissor.getHeight());
             }
         }
@@ -1981,57 +1998,57 @@
      * and then, render the layers targeted at the framebuffer
      */
 
-    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
-    const size_t count = layers.size();
-    const Transform& tr = hw->getTransform();
-    if (cur != end) {
+    ALOGV("Rendering client layers");
+    const Transform& displayTransform = displayDevice->getTransform();
+    if (hwcId >= 0) {
         // we're using h/w composer
-        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
-            const sp<Layer>& layer(layers[i]);
-            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
+        bool firstLayer = true;
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+            const Region clip(dirty.intersect(
+                    displayTransform.transform(layer->visibleRegion)));
+            ALOGV("Layer: %s", layer->getName().string());
+            ALOGV("  Composition type: %s",
+                    to_string(layer->getCompositionType(hwcId)).c_str());
             if (!clip.isEmpty()) {
-                switch (cur->getCompositionType()) {
-                    case HWC_CURSOR_OVERLAY:
-                    case HWC_OVERLAY: {
+                switch (layer->getCompositionType(hwcId)) {
+                    case HWC2::Composition::Cursor:
+                    case HWC2::Composition::Device:
+                    case HWC2::Composition::SolidColor: {
                         const Layer::State& state(layer->getDrawingState());
-                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
-                                && i
-                                && layer->isOpaque(state) && (state.alpha == 0xFF)
-                                && hasGlesComposition) {
+                        if (layer->getClearClientTarget(hwcId) && !firstLayer &&
+                                layer->isOpaque(state) && (state.alpha == 1.0f)
+                                && hasClientComposition) {
                             // never clear the very first layer since we're
                             // guaranteed the FB is already cleared
-                            layer->clearWithOpenGL(hw, clip);
+                            layer->clearWithOpenGL(displayDevice, clip);
                         }
                         break;
                     }
-                    case HWC_FRAMEBUFFER: {
-                        layer->draw(hw, clip);
+                    case HWC2::Composition::Client: {
+                        layer->draw(displayDevice, clip);
                         break;
                     }
-                    case HWC_FRAMEBUFFER_TARGET: {
-                        // this should not happen as the iterator shouldn't
-                        // let us get there.
-                        ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
+                    default:
                         break;
-                    }
                 }
+            } else {
+                ALOGV("  Skipping for empty clip");
             }
-            layer->setAcquireFence(hw, *cur);
+            firstLayer = false;
         }
     } else {
         // we're not using h/w composer
-        for (size_t i=0 ; i<count ; ++i) {
-            const sp<Layer>& layer(layers[i]);
+        for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
             const Region clip(dirty.intersect(
-                    tr.transform(layer->visibleRegion)));
+                    displayTransform.transform(layer->visibleRegion)));
             if (!clip.isEmpty()) {
-                layer->draw(hw, clip);
+                layer->draw(displayDevice, clip);
             }
         }
     }
 
     // disable scissor at the end of the frame
-    engine.disableScissor();
+    mRenderEngine->disableScissor();
     return true;
 }
 
@@ -2233,7 +2250,7 @@
         if (what & layer_state_t::eLayerChanged) {
             // NOTE: index needs to be calculated before we update the state
             ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            if (layer->setLayer(s.z)) {
+            if (layer->setLayer(s.z) && idx >= 0) {
                 mCurrentState.layersSortedByZ.removeAt(idx);
                 mCurrentState.layersSortedByZ.add(layer);
                 // we need traversal (state changed)
@@ -2247,7 +2264,7 @@
             }
         }
         if (what & layer_state_t::eAlphaChanged) {
-            if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+            if (layer->setAlpha(s.alpha))
                 flags |= eTraversalNeeded;
         }
         if (what & layer_state_t::eMatrixChanged) {
@@ -2266,10 +2283,14 @@
             if (layer->setCrop(s.crop))
                 flags |= eTraversalNeeded;
         }
+        if (what & layer_state_t::eFinalCropChanged) {
+            if (layer->setFinalCrop(s.finalCrop))
+                flags |= eTraversalNeeded;
+        }
         if (what & layer_state_t::eLayerStackChanged) {
             // NOTE: index needs to be calculated before we update the state
             ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
-            if (layer->setLayerStack(s.layerStack)) {
+            if (layer->setLayerStack(s.layerStack) && idx >= 0) {
                 mCurrentState.layersSortedByZ.removeAt(idx);
                 mCurrentState.layersSortedByZ.add(layer);
                 // we need traversal (state changed)
@@ -2277,6 +2298,16 @@
                 flags |= eTransactionNeeded|eTraversalNeeded;
             }
         }
+        if (what & layer_state_t::eDeferTransaction) {
+            layer->deferTransactionUntil(s.handle, s.frameNumber);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
+        if (what & layer_state_t::eOverrideScalingModeChanged) {
+            layer->setOverrideScalingMode(s.overrideScalingMode);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
     }
     return flags;
 }
@@ -2410,8 +2441,8 @@
     setTransactionState(state, displays, 0);
     setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
 
-    const nsecs_t period =
-            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+    const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const nsecs_t period = activeConfig->getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(period);
 }
 
@@ -2564,6 +2595,15 @@
                 dumpStaticScreenStats(result);
                 dumpAll = false;
             }
+
+#ifdef ENABLE_FENCE_TRACKING
+            if ((index < numArgs) &&
+                    (args[index] == String16("--fences"))) {
+                index++;
+                mFenceTracker.dump(&result);
+                dumpAll = false;
+            }
+#endif
         }
 
         if (dumpAll) {
@@ -2598,8 +2638,8 @@
         index++;
     }
 
-    const nsecs_t period =
-            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+    const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+    const nsecs_t period = activeConfig->getVsyncPeriod();
     result.appendFormat("%" PRId64 "\n", period);
 
     if (name.isEmpty()) {
@@ -2721,13 +2761,15 @@
     result.append(SyncFeatures::getInstance().toString());
     result.append("\n");
 
+    const auto& activeConfig = mHwc->getActiveConfig(HWC_DISPLAY_PRIMARY);
+
     colorizer.bold(result);
     result.append("DispSync configuration: ");
     colorizer.reset(result);
     result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
             "present offset %d ns (refresh %" PRId64 " ns)",
-        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, PRESENT_TIME_OFFSET_FROM_VSYNC_NS,
-        mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
+        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs,
+        PRESENT_TIME_OFFSET_FROM_VSYNC_NS, activeConfig->getVsyncPeriod());
     result.append("\n");
 
     // Dump static screen stats
@@ -2795,9 +2837,9 @@
             mLastSwapBufferTime/1000.0,
             mLastTransactionTime/1000.0,
             mTransactionFlags,
-            1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
-            hwc.getDpiX(HWC_DISPLAY_PRIMARY),
-            hwc.getDpiY(HWC_DISPLAY_PRIMARY),
+            1e9 / activeConfig->getVsyncPeriod(),
+            activeConfig->getDpiX(),
+            activeConfig->getDpiY(),
             !mGpuToCpuSupported);
 
     result.appendFormat("  eglSwapBuffers time: %f us\n",
@@ -2817,10 +2859,10 @@
     colorizer.bold(result);
     result.append("h/w composer state:\n");
     colorizer.reset(result);
-    result.appendFormat("  h/w composer %s and %s\n",
-            hwc.initCheck()==NO_ERROR ? "present" : "not present",
-                    (mDebugDisableHWC || mDebugRegion || mDaltonize
-                            || mHasColorMatrix) ? "disabled" : "enabled");
+    bool hwcDisabled = mDebugDisableHWC || mDebugRegion || mDaltonize ||
+            mHasColorMatrix;
+    result.appendFormat("  h/w composer %s\n",
+            hwcDisabled ? "disabled" : "enabled");
     hwc.dump(result);
 
     /*
@@ -2877,6 +2919,7 @@
         case CLEAR_ANIMATION_FRAME_STATS:
         case GET_ANIMATION_FRAME_STATS:
         case SET_POWER_MODE:
+        case GET_HDR_CAPABILITIES:
         {
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
@@ -3127,8 +3170,12 @@
     GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl)
     :   impl(impl),
         looper(new Looper(true)),
+        result(NO_ERROR),
         exitPending(false),
-        exitRequested(false)
+        exitRequested(false),
+        code(0),
+        data(NULL),
+        reply(NULL)
     {}
 
     // Binder thread
@@ -3166,14 +3213,7 @@
     // if we have secure windows on this display, never allow the screen capture
     // unless the producer interface is local (i.e.: we can take a screenshot for
     // ourselves).
-    if (!IInterface::asBinder(producer)->localBinder()) {
-        Mutex::Autolock _l(mStateLock);
-        sp<const DisplayDevice> hw(getDisplayDevice(display));
-        if (hw->getSecureLayerVisible()) {
-            ALOGW("FB is protected: PERMISSION_DENIED");
-            return PERMISSION_DENIED;
-        }
-    }
+    bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
 
     // Convert to surfaceflinger's internal rotation type.
     Transform::orientation_flags rotationFlags;
@@ -3206,19 +3246,22 @@
         bool useIdentityTransform;
         Transform::orientation_flags rotation;
         status_t result;
+        bool isLocalScreenshot;
     public:
         MessageCaptureScreen(SurfaceFlinger* flinger,
                 const sp<IBinder>& display,
                 const sp<IGraphicBufferProducer>& producer,
                 Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
                 uint32_t minLayerZ, uint32_t maxLayerZ,
-                bool useIdentityTransform, Transform::orientation_flags rotation)
+                bool useIdentityTransform,
+                Transform::orientation_flags rotation,
+                bool isLocalScreenshot)
             : flinger(flinger), display(display), producer(producer),
               sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
               minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
               useIdentityTransform(useIdentityTransform),
-              rotation(rotation),
-              result(PERMISSION_DENIED)
+              rotation(rotation), result(PERMISSION_DENIED),
+              isLocalScreenshot(isLocalScreenshot)
         {
         }
         status_t getResult() const {
@@ -3229,7 +3272,7 @@
             sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
             result = flinger->captureScreenImplLocked(hw, producer,
                     sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-                    useIdentityTransform, rotation);
+                    useIdentityTransform, rotation, isLocalScreenshot);
             static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
             return true;
         }
@@ -3252,7 +3295,7 @@
     sp<MessageBase> msg = new MessageCaptureScreen(this,
             display, IGraphicBufferProducer::asInterface( wrapper ),
             sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
-            useIdentityTransform, rotationFlags);
+            useIdentityTransform, rotationFlags, isLocalScreenshot);
 
     status_t res = postMessageAsync(msg);
     if (res == NO_ERROR) {
@@ -3325,8 +3368,6 @@
         }
     }
 
-    // compositionComplete is needed for older driver
-    hw->compositionComplete();
     hw->setViewportAndProjection();
 }
 
@@ -3336,7 +3377,8 @@
         const sp<IGraphicBufferProducer>& producer,
         Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
         uint32_t minLayerZ, uint32_t maxLayerZ,
-        bool useIdentityTransform, Transform::orientation_flags rotation)
+        bool useIdentityTransform, Transform::orientation_flags rotation,
+        bool isLocalScreenshot)
 {
     ATRACE_CALL();
 
@@ -3357,6 +3399,24 @@
     reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
     reqHeight = (!reqHeight) ? hw_h : reqHeight;
 
+    bool secureLayerIsVisible = false;
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
+    for (size_t i = 0 ; i < count ; ++i) {
+        const sp<Layer>& layer(layers[i]);
+        const Layer::State& state(layer->getDrawingState());
+        if (state.layerStack == hw->getLayerStack() && state.z >= minLayerZ &&
+                state.z <= maxLayerZ && layer->isVisible() &&
+                layer->isSecure()) {
+            secureLayerIsVisible = true;
+        }
+    }
+
+    if (!isLocalScreenshot && secureLayerIsVisible) {
+        ALOGW("FB is protected: PERMISSION_DENIED");
+        return PERMISSION_DENIED;
+    }
+
     // create a surface (because we're a producer, and we need to
     // dequeue/queue a buffer)
     sp<Surface> sur = new Surface(producer, false);
@@ -3446,14 +3506,18 @@
                     } else {
                         ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
                         result = INVALID_OPERATION;
+                        window->cancelBuffer(window, buffer, syncFd);
+                        buffer = NULL;
                     }
                     // destroy our image
                     eglDestroyImageKHR(mEGLDisplay, image);
                 } else {
                     result = BAD_VALUE;
                 }
-                // queueBuffer takes ownership of syncFd
-                result = window->queueBuffer(window, buffer, syncFd);
+                if (buffer) {
+                    // queueBuffer takes ownership of syncFd
+                    result = window->queueBuffer(window, buffer, syncFd);
+                }
             }
         } else {
             result = BAD_VALUE;
@@ -3484,7 +3548,7 @@
             const bool visible = (state.layerStack == hw->getLayerStack())
                                 && (state.z >= minLayerZ && state.z <= maxLayerZ)
                                 && (layer->isVisible());
-            ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x",
+            ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f",
                     visible ? '+' : '-',
                             i, layer->getName().string(), state.layerStack, state.z,
                             layer->isVisible(), state.flags, state.alpha);
@@ -3524,11 +3588,22 @@
 // ---------------------------------------------------------------------------
 
 SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
-    : type(DisplayDevice::DISPLAY_ID_INVALID), width(0), height(0) {
+    : type(DisplayDevice::DISPLAY_ID_INVALID),
+      layerStack(DisplayDevice::NO_LAYER_STACK),
+      orientation(0),
+      width(0),
+      height(0),
+      isSecure(false) {
 }
 
-SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(DisplayDevice::DisplayType type)
-    : type(type), layerStack(DisplayDevice::NO_LAYER_STACK), orientation(0), width(0), height(0) {
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
+    DisplayDevice::DisplayType type, bool isSecure)
+    : type(type),
+      layerStack(DisplayDevice::NO_LAYER_STACK),
+      orientation(0),
+      width(0),
+      height(0),
+      isSecure(isSecure) {
     viewport.makeInvalid();
     frame.makeInvalid();
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index b3baadd..633e956 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -50,6 +50,7 @@
 #include "Barrier.h"
 #include "DisplayDevice.h"
 #include "DispSync.h"
+#include "FenceTracker.h"
 #include "FrameTracker.h"
 #include "MessageQueue.h"
 
@@ -119,7 +120,11 @@
 
     // enable/disable h/w composer event
     // TODO: this should be made accessible only to EventThread
+#ifdef USE_HWC2
+    void setVsyncEnabled(int disp, int enabled);
+#else
     void eventControl(int disp, int event, int enabled);
+#endif
 
     // called on the main thread by MessageQueue when an internal message
     // is received
@@ -162,7 +167,7 @@
 
     struct DisplayDeviceState {
         DisplayDeviceState();
-        DisplayDeviceState(DisplayDevice::DisplayType type);
+        DisplayDeviceState(DisplayDevice::DisplayType type, bool isSecure);
         bool isValid() const { return type >= 0; }
         bool isMainDisplay() const { return type == DisplayDevice::DISPLAY_PRIMARY; }
         bool isVirtualDisplay() const { return type >= DisplayDevice::DISPLAY_VIRTUAL; }
@@ -217,6 +222,8 @@
     virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
     virtual status_t clearAnimationFrameStats();
     virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
+    virtual status_t getHdrCapabilities(const sp<IBinder>& display,
+            HdrCapabilities* outCapabilities) const;
 
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
@@ -329,7 +336,8 @@
             const sp<IGraphicBufferProducer>& producer,
             Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
             uint32_t minLayerZ, uint32_t maxLayerZ,
-            bool useIdentityTransform, Transform::orientation_flags rotation);
+            bool useIdentityTransform, Transform::orientation_flags rotation,
+            bool isLocalScreenshot);
 
     /* ------------------------------------------------------------------------
      * EGL
@@ -360,8 +368,9 @@
     // region of all screens presenting this layer stack.
     void invalidateLayerStack(uint32_t layerStack, const Region& dirty);
 
-    // allocate a h/w composer display id
+#ifndef USE_HWC2
     int32_t allocateHwcDisplayId(DisplayDevice::DisplayType type);
+#endif
 
     /* ------------------------------------------------------------------------
      * H/W composer
@@ -378,7 +387,7 @@
             Region& dirtyRegion, Region& opaqueRegion);
 
     void preComposition();
-    void postComposition();
+    void postComposition(nsecs_t refreshStartTime);
     void rebuildLayerStacks();
     void setUpHWComposer();
     void doComposition();
@@ -400,8 +409,11 @@
      * VSync
      */
      void enableHardwareVsync();
-     void disableHardwareVsync(bool makeUnavailable);
      void resyncToHardwareVsync(bool makeAvailable);
+     void disableHardwareVsync(bool makeUnavailable);
+public:
+     void resyncWithRateLimit();
+private:
 
     /* ------------------------------------------------------------------------
      * Debugging & dumpsys
@@ -457,8 +469,15 @@
     // don't need synchronization
     State mDrawingState;
     bool mVisibleRegionsDirty;
+#ifndef USE_HWC2
     bool mHwWorkListDirty;
+#else
+    bool mGeometryInvalid;
+#endif
     bool mAnimCompositionPending;
+#ifdef USE_HWC2
+    std::vector<sp<Layer>> mLayersWithQueuedFrames;
+#endif
 
     // this may only be written from the main thread with mStateLock held
     // it may be read from other threads with mStateLock held
@@ -475,6 +494,7 @@
     nsecs_t mLastTransactionTime;
     bool mBootFinished;
     bool mForceFullDamage;
+    FenceTracker mFenceTracker;
 
     // these are thread safe
     mutable MessageQueue mEventQueue;
@@ -505,7 +525,7 @@
     static const size_t NUM_BUCKETS = 8; // < 1-7, 7+
     nsecs_t mFrameBuckets[NUM_BUCKETS];
     nsecs_t mTotalTime;
-    nsecs_t mLastSwapTime;
+    std::atomic<nsecs_t> mLastSwapTime;
 };
 
 }; // namespace android
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index ed1f31b..c71b3bc 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -32,7 +32,8 @@
 // ---------------------------------------------------------------------------
 
 status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
-        const DispSync& dispSync, uint64_t maxFrameNumber)
+        const DispSync& dispSync, bool* autoRefresh, bool* queuedBuffer,
+        uint64_t maxFrameNumber)
 {
     ATRACE_CALL();
     ALOGV("updateTexImage");
@@ -68,18 +69,29 @@
         return err;
     }
 
-
     // We call the rejecter here, in case the caller has a reason to
     // not accept this buffer.  This is used by SurfaceFlinger to
     // reject buffers which have the wrong size
-    int buf = item.mBuf;
-    if (rejecter && rejecter->reject(mSlots[buf].mGraphicBuffer, item)) {
-        releaseBufferLocked(buf, mSlots[buf].mGraphicBuffer, EGL_NO_SYNC_KHR);
+    int slot = item.mSlot;
+    if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
+        releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer, EGL_NO_SYNC_KHR);
         return BUFFER_REJECTED;
     }
 
+    if (autoRefresh) {
+        *autoRefresh = item.mAutoRefresh;
+    }
+
+    if (queuedBuffer) {
+        *queuedBuffer = item.mQueuedBuffer;
+    }
+
     // Release the previous buffer.
+#ifdef USE_HWC2
+    err = updateAndReleaseLocked(item, &mPendingRelease);
+#else
     err = updateAndReleaseLocked(item);
+#endif
     if (err != NO_ERROR) {
         return err;
     }
@@ -175,6 +187,50 @@
     return nextRefresh + extraPadding;
 }
 
+#ifdef USE_HWC2
+void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence)
+{
+    mPrevReleaseFence = fence;
+    if (!mPendingRelease.isPending) {
+        GLConsumer::setReleaseFence(fence);
+        return;
+    }
+    auto currentTexture = mPendingRelease.currentTexture;
+    if (fence->isValid() &&
+            currentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
+        status_t result = addReleaseFence(currentTexture,
+                mPendingRelease.graphicBuffer, fence);
+        ALOGE_IF(result != NO_ERROR, "setReleaseFence: failed to add the"
+                " fence: %s (%d)", strerror(-result), result);
+    }
+}
+
+void SurfaceFlingerConsumer::releasePendingBuffer()
+{
+    if (!mPendingRelease.isPending) {
+        ALOGV("Pending buffer already released");
+        return;
+    }
+    ALOGV("Releasing pending buffer");
+    Mutex::Autolock lock(mMutex);
+    status_t result = releaseBufferLocked(mPendingRelease.currentTexture,
+            mPendingRelease.graphicBuffer, mPendingRelease.display,
+            mPendingRelease.fence);
+    ALOGE_IF(result != NO_ERROR, "releasePendingBuffer failed: %s (%d)",
+            strerror(-result), result);
+    mPendingRelease = PendingRelease();
+}
+#else
+void SurfaceFlingerConsumer::setReleaseFence(const sp<Fence>& fence) {
+    mPrevReleaseFence = fence;
+    GLConsumer::setReleaseFence(fence);
+}
+#endif
+
+sp<Fence> SurfaceFlingerConsumer::getPrevReleaseFence() const {
+    return mPrevReleaseFence;
+}
+
 void SurfaceFlingerConsumer::setContentsChangedListener(
         const wp<ContentsChangedListener>& listener) {
     setFrameAvailableListener(listener);
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 779e5b7..51b002f 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -37,7 +37,8 @@
     SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
             uint32_t tex)
         : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
-          mTransformToDisplayInverse(false), mSurfaceDamage()
+          mTransformToDisplayInverse(false), mSurfaceDamage(),
+          mPrevReleaseFence(Fence::NO_FENCE)
     {}
 
     class BufferRejecter {
@@ -57,6 +58,7 @@
     // this does not guarantee that the buffer has been bound to the GL
     // texture.
     status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
+            bool* autoRefresh, bool* queuedBuffer,
             uint64_t maxFrameNumber = 0);
 
     // See GLConsumer::bindTextureImageLocked().
@@ -74,6 +76,12 @@
 
     nsecs_t computeExpectedPresent(const DispSync& dispSync);
 
+    virtual void setReleaseFence(const sp<Fence>& fence) override;
+    sp<Fence> getPrevReleaseFence() const;
+#ifdef USE_HWC2
+    void releasePendingBuffer();
+#endif
+
 private:
     virtual void onSidebandStreamChanged();
 
@@ -86,6 +94,15 @@
 
     // The portion of this surface that has changed since the previous frame
     Region mSurfaceDamage;
+
+#ifdef USE_HWC2
+    // A release that is pending on the receipt of a new release fence from
+    // presentDisplay
+    PendingRelease mPendingRelease;
+#endif
+
+    // The release fence of the already displayed buffer (previous frame).
+    sp<Fence> mPrevReleaseFence;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
new file mode 100644
index 0000000..00700ab
--- /dev/null
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -0,0 +1,3647 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <math.h>
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <stdatomic.h>
+
+#include <EGL/egl.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/MemoryHeapBase.h>
+#include <binder/PermissionCache.h>
+
+#include <ui/DisplayInfo.h>
+#include <ui/DisplayStatInfo.h>
+
+#include <gui/BitTube.h>
+#include <gui/BufferQueue.h>
+#include <gui/GuiConfig.h>
+#include <gui/IDisplayEventConnection.h>
+#include <gui/Surface.h>
+#include <gui/GraphicBufferAlloc.h>
+
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/HdrCapabilities.h>
+#include <ui/PixelFormat.h>
+#include <ui/UiConfig.h>
+
+#include <utils/misc.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/StopWatch.h>
+#include <utils/Timers.h>
+#include <utils/Trace.h>
+
+#include <private/android_filesystem_config.h>
+#include <private/gui/SyncFeatures.h>
+
+#include "Client.h"
+#include "clz.h"
+#include "Colorizer.h"
+#include "DdmConnection.h"
+#include "DisplayDevice.h"
+#include "DispSync.h"
+#include "EventControlThread.h"
+#include "EventThread.h"
+#include "Layer.h"
+#include "LayerDim.h"
+#include "SurfaceFlinger.h"
+
+#include "DisplayHardware/FramebufferSurface.h"
+#include "DisplayHardware/HWComposer.h"
+#include "DisplayHardware/VirtualDisplaySurface.h"
+
+#include "Effects/Daltonizer.h"
+
+#include "RenderEngine/RenderEngine.h"
+#include <cutils/compiler.h>
+
+#define DISPLAY_COUNT       1
+
+/*
+ * DEBUG_SCREENSHOTS: set to true to check that screenshots are not all
+ * black pixels.
+ */
+#define DEBUG_SCREENSHOTS   false
+
+EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
+
+namespace android {
+
+// This is the phase offset in nanoseconds of the software vsync event
+// relative to the vsync event reported by HWComposer.  The software vsync
+// event is when SurfaceFlinger and Choreographer-based applications run each
+// frame.
+//
+// This phase offset allows adjustment of the minimum latency from application
+// wake-up (by Choregographer) time to the time at which the resulting window
+// image is displayed.  This value may be either positive (after the HW vsync)
+// or negative (before the HW vsync).  Setting it to 0 will result in a
+// minimum latency of two vsync periods because the app and SurfaceFlinger
+// will run just after the HW vsync.  Setting it to a positive number will
+// result in the minimum latency being:
+//
+//     (2 * VSYNC_PERIOD - (vsyncPhaseOffsetNs % VSYNC_PERIOD))
+//
+// Note that reducing this latency makes it more likely for the applications
+// to not have their window content image ready in time.  When this happens
+// the latency will end up being an additional vsync period, and animations
+// will hiccup.  Therefore, this latency should be tuned somewhat
+// conservatively (or at least with awareness of the trade-off being made).
+static const int64_t vsyncPhaseOffsetNs = VSYNC_EVENT_PHASE_OFFSET_NS;
+
+// This is the phase offset at which SurfaceFlinger's composition runs.
+static const int64_t sfVsyncPhaseOffsetNs = SF_VSYNC_EVENT_PHASE_OFFSET_NS;
+
+// ---------------------------------------------------------------------------
+
+const String16 sHardwareTest("android.permission.HARDWARE_TEST");
+const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
+const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
+const String16 sDump("android.permission.DUMP");
+
+// ---------------------------------------------------------------------------
+
+SurfaceFlinger::SurfaceFlinger()
+    :   BnSurfaceComposer(),
+        mTransactionFlags(0),
+        mTransactionPending(false),
+        mAnimTransactionPending(false),
+        mLayersRemoved(false),
+        mRepaintEverything(0),
+        mRenderEngine(NULL),
+        mBootTime(systemTime()),
+        mVisibleRegionsDirty(false),
+        mHwWorkListDirty(false),
+        mAnimCompositionPending(false),
+        mDebugRegion(0),
+        mDebugDDMS(0),
+        mDebugDisableHWC(0),
+        mDebugDisableTransformHint(0),
+        mDebugInSwapBuffers(0),
+        mLastSwapBufferTime(0),
+        mDebugInTransaction(0),
+        mLastTransactionTime(0),
+        mBootFinished(false),
+        mForceFullDamage(false),
+        mPrimaryDispSync("PrimaryDispSync"),
+        mPrimaryHWVsyncEnabled(false),
+        mHWVsyncAvailable(false),
+        mDaltonize(false),
+        mHasColorMatrix(false),
+        mHasPoweredOff(false),
+        mFrameBuckets(),
+        mTotalTime(0),
+        mLastSwapTime(0)
+{
+    ALOGI("SurfaceFlinger is starting");
+
+    // debugging stuff...
+    char value[PROPERTY_VALUE_MAX];
+
+    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
+    mGpuToCpuSupported = !atoi(value);
+
+    property_get("debug.sf.drop_missed_frames", value, "0");
+    mDropMissedFrames = atoi(value);
+
+    property_get("debug.sf.showupdates", value, "0");
+    mDebugRegion = atoi(value);
+
+    property_get("debug.sf.ddms", value, "0");
+    mDebugDDMS = atoi(value);
+    if (mDebugDDMS) {
+        if (!startDdmConnection()) {
+            // start failed, and DDMS debugging not enabled
+            mDebugDDMS = 0;
+        }
+    }
+    ALOGI_IF(mDebugRegion, "showupdates enabled");
+    ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
+}
+
+void SurfaceFlinger::onFirstRef()
+{
+    mEventQueue.init(this);
+}
+
+SurfaceFlinger::~SurfaceFlinger()
+{
+    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(display);
+}
+
+void SurfaceFlinger::binderDied(const wp<IBinder>& /* who */)
+{
+    // the window manager died on us. prepare its eulogy.
+
+    // restore initial conditions (default device unblank, etc)
+    initializeDisplays();
+
+    // restart the boot-animation
+    startBootAnim();
+}
+
+sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()
+{
+    sp<ISurfaceComposerClient> bclient;
+    sp<Client> client(new Client(this));
+    status_t err = client->initCheck();
+    if (err == NO_ERROR) {
+        bclient = client;
+    }
+    return bclient;
+}
+
+sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName,
+        bool secure)
+{
+    class DisplayToken : public BBinder {
+        sp<SurfaceFlinger> flinger;
+        virtual ~DisplayToken() {
+             // no more references, this display must be terminated
+             Mutex::Autolock _l(flinger->mStateLock);
+             flinger->mCurrentState.displays.removeItem(this);
+             flinger->setTransactionFlags(eDisplayTransactionNeeded);
+         }
+     public:
+        DisplayToken(const sp<SurfaceFlinger>& flinger)
+            : flinger(flinger) {
+        }
+    };
+
+    sp<BBinder> token = new DisplayToken(this);
+
+    Mutex::Autolock _l(mStateLock);
+    DisplayDeviceState info(DisplayDevice::DISPLAY_VIRTUAL, secure);
+    info.displayName = displayName;
+    mCurrentState.displays.add(token, info);
+
+    return token;
+}
+
+void SurfaceFlinger::destroyDisplay(const sp<IBinder>& display) {
+    Mutex::Autolock _l(mStateLock);
+
+    ssize_t idx = mCurrentState.displays.indexOfKey(display);
+    if (idx < 0) {
+        ALOGW("destroyDisplay: invalid display token");
+        return;
+    }
+
+    const DisplayDeviceState& info(mCurrentState.displays.valueAt(idx));
+    if (!info.isVirtualDisplay()) {
+        ALOGE("destroyDisplay called for non-virtual display");
+        return;
+    }
+
+    mCurrentState.displays.removeItemsAt(idx);
+    setTransactionFlags(eDisplayTransactionNeeded);
+}
+
+void SurfaceFlinger::createBuiltinDisplayLocked(DisplayDevice::DisplayType type) {
+    ALOGW_IF(mBuiltinDisplays[type],
+            "Overwriting display token for display type %d", type);
+    mBuiltinDisplays[type] = new BBinder();
+    // All non-virtual displays are currently considered secure.
+    DisplayDeviceState info(type, true);
+    mCurrentState.displays.add(mBuiltinDisplays[type], info);
+}
+
+sp<IBinder> SurfaceFlinger::getBuiltInDisplay(int32_t id) {
+    if (uint32_t(id) >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        ALOGE("getDefaultDisplay: id=%d is not a valid default display id", id);
+        return NULL;
+    }
+    return mBuiltinDisplays[id];
+}
+
+sp<IGraphicBufferAlloc> SurfaceFlinger::createGraphicBufferAlloc()
+{
+    sp<GraphicBufferAlloc> gba(new GraphicBufferAlloc());
+    return gba;
+}
+
+void SurfaceFlinger::bootFinished()
+{
+    const nsecs_t now = systemTime();
+    const nsecs_t duration = now - mBootTime;
+    ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
+    mBootFinished = true;
+
+    // wait patiently for the window manager death
+    const String16 name("window");
+    sp<IBinder> window(defaultServiceManager()->getService(name));
+    if (window != 0) {
+        window->linkToDeath(static_cast<IBinder::DeathRecipient*>(this));
+    }
+
+    // stop boot animation
+    // formerly we would just kill the process, but we now ask it to exit so it
+    // can choose where to stop the animation.
+    property_set("service.bootanim.exit", "1");
+
+    const int LOGTAG_SF_STOP_BOOTANIM = 60110;
+    LOG_EVENT_LONG(LOGTAG_SF_STOP_BOOTANIM,
+                   ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
+}
+
+void SurfaceFlinger::deleteTextureAsync(uint32_t texture) {
+    class MessageDestroyGLTexture : public MessageBase {
+        RenderEngine& engine;
+        uint32_t texture;
+    public:
+        MessageDestroyGLTexture(RenderEngine& engine, uint32_t texture)
+            : engine(engine), texture(texture) {
+        }
+        virtual bool handler() {
+            engine.deleteTextures(1, &texture);
+            return true;
+        }
+    };
+    postMessageAsync(new MessageDestroyGLTexture(getRenderEngine(), texture));
+}
+
+class DispSyncSource : public VSyncSource, private DispSync::Callback {
+public:
+    DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync,
+        const char* name) :
+            mName(name),
+            mValue(0),
+            mTraceVsync(traceVsync),
+            mVsyncOnLabel(String8::format("VsyncOn-%s", name)),
+            mVsyncEventLabel(String8::format("VSYNC-%s", name)),
+            mDispSync(dispSync),
+            mCallbackMutex(),
+            mCallback(),
+            mVsyncMutex(),
+            mPhaseOffset(phaseOffset),
+            mEnabled(false) {}
+
+    virtual ~DispSyncSource() {}
+
+    virtual void setVSyncEnabled(bool enable) {
+        Mutex::Autolock lock(mVsyncMutex);
+        if (enable) {
+            status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
+                    static_cast<DispSync::Callback*>(this));
+            if (err != NO_ERROR) {
+                ALOGE("error registering vsync callback: %s (%d)",
+                        strerror(-err), err);
+            }
+            //ATRACE_INT(mVsyncOnLabel.string(), 1);
+        } else {
+            status_t err = mDispSync->removeEventListener(
+                    static_cast<DispSync::Callback*>(this));
+            if (err != NO_ERROR) {
+                ALOGE("error unregistering vsync callback: %s (%d)",
+                        strerror(-err), err);
+            }
+            //ATRACE_INT(mVsyncOnLabel.string(), 0);
+        }
+        mEnabled = enable;
+    }
+
+    virtual void setCallback(const sp<VSyncSource::Callback>& callback) {
+        Mutex::Autolock lock(mCallbackMutex);
+        mCallback = callback;
+    }
+
+    virtual void setPhaseOffset(nsecs_t phaseOffset) {
+        Mutex::Autolock lock(mVsyncMutex);
+
+        // Normalize phaseOffset to [0, period)
+        auto period = mDispSync->getPeriod();
+        phaseOffset %= period;
+        if (phaseOffset < 0) {
+            // If we're here, then phaseOffset is in (-period, 0). After this
+            // operation, it will be in (0, period)
+            phaseOffset += period;
+        }
+        mPhaseOffset = phaseOffset;
+
+        // If we're not enabled, we don't need to mess with the listeners
+        if (!mEnabled) {
+            return;
+        }
+
+        // Remove the listener with the old offset
+        status_t err = mDispSync->removeEventListener(
+                static_cast<DispSync::Callback*>(this));
+        if (err != NO_ERROR) {
+            ALOGE("error unregistering vsync callback: %s (%d)",
+                    strerror(-err), err);
+        }
+
+        // Add a listener with the new offset
+        err = mDispSync->addEventListener(mName, mPhaseOffset,
+                static_cast<DispSync::Callback*>(this));
+        if (err != NO_ERROR) {
+            ALOGE("error registering vsync callback: %s (%d)",
+                    strerror(-err), err);
+        }
+    }
+
+private:
+    virtual void onDispSyncEvent(nsecs_t when) {
+        sp<VSyncSource::Callback> callback;
+        {
+            Mutex::Autolock lock(mCallbackMutex);
+            callback = mCallback;
+
+            if (mTraceVsync) {
+                mValue = (mValue + 1) % 2;
+                ATRACE_INT(mVsyncEventLabel.string(), mValue);
+            }
+        }
+
+        if (callback != NULL) {
+            callback->onVSyncEvent(when);
+        }
+    }
+
+    const char* const mName;
+
+    int mValue;
+
+    const bool mTraceVsync;
+    const String8 mVsyncOnLabel;
+    const String8 mVsyncEventLabel;
+
+    DispSync* mDispSync;
+
+    Mutex mCallbackMutex; // Protects the following
+    sp<VSyncSource::Callback> mCallback;
+
+    Mutex mVsyncMutex; // Protects the following
+    nsecs_t mPhaseOffset;
+    bool mEnabled;
+};
+
+void SurfaceFlinger::init() {
+    ALOGI(  "SurfaceFlinger's main thread ready to run. "
+            "Initializing graphics H/W...");
+
+    Mutex::Autolock _l(mStateLock);
+
+    // initialize EGL for the default display
+    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(mEGLDisplay, NULL, NULL);
+
+    // start the EventThread
+    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            vsyncPhaseOffsetNs, true, "app");
+    mEventThread = new EventThread(vsyncSrc, *this);
+    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
+            sfVsyncPhaseOffsetNs, true, "sf");
+    mSFEventThread = new EventThread(sfVsyncSrc, *this);
+    mEventQueue.setEventThread(mSFEventThread);
+
+    // Initialize the H/W composer object.  There may or may not be an
+    // actual hardware composer underneath.
+    mHwc = new HWComposer(this,
+            *static_cast<HWComposer::EventHandler *>(this));
+
+    // get a RenderEngine for the given display / config (can't fail)
+    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
+
+    // retrieve the EGL context that was selected/created
+    mEGLContext = mRenderEngine->getEGLContext();
+
+    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
+            "couldn't create EGLContext");
+
+    // initialize our non-virtual displays
+    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
+        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
+        // set-up the displays that are already connected
+        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
+            // All non-virtual displays are currently considered secure.
+            bool isSecure = true;
+            createBuiltinDisplayLocked(type);
+            wp<IBinder> token = mBuiltinDisplays[i];
+
+            sp<IGraphicBufferProducer> producer;
+            sp<IGraphicBufferConsumer> consumer;
+            BufferQueue::createBufferQueue(&producer, &consumer,
+                    new GraphicBufferAlloc());
+
+            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
+                    consumer);
+            int32_t hwcId = allocateHwcDisplayId(type);
+            sp<DisplayDevice> hw = new DisplayDevice(this,
+                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
+                    fbs, producer,
+                    mRenderEngine->getEGLConfig());
+            if (i > DisplayDevice::DISPLAY_PRIMARY) {
+                // FIXME: currently we don't get blank/unblank requests
+                // for displays other than the main display, so we always
+                // assume a connected display is unblanked.
+                ALOGD("marking display %zu as acquired/unblanked", i);
+                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
+            }
+            mDisplays.add(token, hw);
+        }
+    }
+
+    // make the GLContext current so that we can create textures when creating Layers
+    // (which may happens before we render something)
+    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+
+    mEventControlThread = new EventControlThread(this);
+    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
+
+    // set a fake vsync period if there is no HWComposer
+    if (mHwc->initCheck() != NO_ERROR) {
+        mPrimaryDispSync.setPeriod(16666667);
+    }
+
+    // initialize our drawing state
+    mDrawingState = mCurrentState;
+
+    // set initial conditions (e.g. unblank default device)
+    initializeDisplays();
+
+    // start boot animation
+    startBootAnim();
+}
+
+int32_t SurfaceFlinger::allocateHwcDisplayId(DisplayDevice::DisplayType type) {
+    return (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) ?
+            type : mHwc->allocateDisplayId();
+}
+
+void SurfaceFlinger::startBootAnim() {
+    // start boot animation
+    property_set("service.bootanim.exit", "0");
+    property_set("ctl.start", "bootanim");
+}
+
+size_t SurfaceFlinger::getMaxTextureSize() const {
+    return mRenderEngine->getMaxTextureSize();
+}
+
+size_t SurfaceFlinger::getMaxViewportDims() const {
+    return mRenderEngine->getMaxViewportDims();
+}
+
+// ----------------------------------------------------------------------------
+
+bool SurfaceFlinger::authenticateSurfaceTexture(
+        const sp<IGraphicBufferProducer>& bufferProducer) const {
+    Mutex::Autolock _l(mStateLock);
+    sp<IBinder> surfaceTextureBinder(IInterface::asBinder(bufferProducer));
+    return mGraphicBufferProducerList.indexOf(surfaceTextureBinder) >= 0;
+}
+
+status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& display,
+        Vector<DisplayInfo>* configs) {
+    if ((configs == NULL) || (display.get() == NULL)) {
+        return BAD_VALUE;
+    }
+
+    if (!display.get())
+        return NAME_NOT_FOUND;
+
+    int32_t type = NAME_NOT_FOUND;
+    for (int i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
+        if (display == mBuiltinDisplays[i]) {
+            type = i;
+            break;
+        }
+    }
+
+    if (type < 0) {
+        return type;
+    }
+
+    // TODO: Not sure if display density should handled by SF any longer
+    class Density {
+        static int getDensityFromProperty(char const* propName) {
+            char property[PROPERTY_VALUE_MAX];
+            int density = 0;
+            if (property_get(propName, property, NULL) > 0) {
+                density = atoi(property);
+            }
+            return density;
+        }
+    public:
+        static int getEmuDensity() {
+            return getDensityFromProperty("qemu.sf.lcd_density"); }
+        static int getBuildDensity()  {
+            return getDensityFromProperty("ro.sf.lcd_density"); }
+    };
+
+    configs->clear();
+
+    const Vector<HWComposer::DisplayConfig>& hwConfigs =
+            getHwComposer().getConfigs(type);
+    for (size_t c = 0; c < hwConfigs.size(); ++c) {
+        const HWComposer::DisplayConfig& hwConfig = hwConfigs[c];
+        DisplayInfo info = DisplayInfo();
+
+        float xdpi = hwConfig.xdpi;
+        float ydpi = hwConfig.ydpi;
+
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // The density of the device is provided by a build property
+            float density = Density::getBuildDensity() / 160.0f;
+            if (density == 0) {
+                // the build doesn't provide a density -- this is wrong!
+                // use xdpi instead
+                ALOGE("ro.sf.lcd_density must be defined as a build property");
+                density = xdpi / 160.0f;
+            }
+            if (Density::getEmuDensity()) {
+                // if "qemu.sf.lcd_density" is specified, it overrides everything
+                xdpi = ydpi = density = Density::getEmuDensity();
+                density /= 160.0f;
+            }
+            info.density = density;
+
+            // TODO: this needs to go away (currently needed only by webkit)
+            sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+            info.orientation = hw->getOrientation();
+        } else {
+            // TODO: where should this value come from?
+            static const int TV_DENSITY = 213;
+            info.density = TV_DENSITY / 160.0f;
+            info.orientation = 0;
+        }
+
+        info.w = hwConfig.width;
+        info.h = hwConfig.height;
+        info.xdpi = xdpi;
+        info.ydpi = ydpi;
+        info.fps = float(1e9 / hwConfig.refresh);
+        info.appVsyncOffset = VSYNC_EVENT_PHASE_OFFSET_NS;
+        info.colorTransform = hwConfig.colorTransform;
+
+        // This is how far in advance a buffer must be queued for
+        // presentation at a given time.  If you want a buffer to appear
+        // on the screen at time N, you must submit the buffer before
+        // (N - presentationDeadline).
+        //
+        // Normally it's one full refresh period (to give SF a chance to
+        // latch the buffer), but this can be reduced by configuring a
+        // DispSync offset.  Any additional delays introduced by the hardware
+        // composer or panel must be accounted for here.
+        //
+        // We add an additional 1ms to allow for processing time and
+        // differences between the ideal and actual refresh rate.
+        info.presentationDeadline =
+                hwConfig.refresh - SF_VSYNC_EVENT_PHASE_OFFSET_NS + 1000000;
+
+        // All non-virtual displays are currently considered secure.
+        info.secure = true;
+
+        configs->push_back(info);
+    }
+
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>& /* display */,
+        DisplayStatInfo* stats) {
+    if (stats == NULL) {
+        return BAD_VALUE;
+    }
+
+    // FIXME for now we always return stats for the primary display
+    memset(stats, 0, sizeof(*stats));
+    stats->vsyncTime   = mPrimaryDispSync.computeNextRefresh(0);
+    stats->vsyncPeriod = mPrimaryDispSync.getPeriod();
+    return NO_ERROR;
+}
+
+int SurfaceFlinger::getActiveConfig(const sp<IBinder>& display) {
+    sp<DisplayDevice> device(getDisplayDevice(display));
+    if (device != NULL) {
+        return device->getActiveConfig();
+    }
+    return BAD_VALUE;
+}
+
+void SurfaceFlinger::setActiveConfigInternal(const sp<DisplayDevice>& hw, int mode) {
+    ALOGD("Set active config mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+          this);
+    int32_t type = hw->getDisplayType();
+    int currentMode = hw->getActiveConfig();
+
+    if (mode == currentMode) {
+        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
+        return;
+    }
+
+    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        ALOGW("Trying to set config for virtual display");
+        return;
+    }
+
+    hw->setActiveConfig(mode);
+    getHwComposer().setActiveConfig(type, mode);
+}
+
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& display, int mode) {
+    class MessageSetActiveConfig: public MessageBase {
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
+        int mMode;
+    public:
+        MessageSetActiveConfig(SurfaceFlinger& flinger, const sp<IBinder>& disp,
+                               int mode) :
+            mFlinger(flinger), mDisplay(disp) { mMode = mode; }
+        virtual bool handler() {
+            Vector<DisplayInfo> configs;
+            mFlinger.getDisplayConfigs(mDisplay, &configs);
+            if (mMode < 0 || mMode >= static_cast<int>(configs.size())) {
+                ALOGE("Attempt to set active config = %d for display with %zu configs",
+                        mMode, configs.size());
+            }
+            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == NULL) {
+                ALOGE("Attempt to set active config = %d for null display %p",
+                        mMode, mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
+                ALOGW("Attempt to set active config = %d for virtual display",
+                        mMode);
+            } else {
+                mFlinger.setActiveConfigInternal(hw, mMode);
+            }
+            return true;
+        }
+    };
+    sp<MessageBase> msg = new MessageSetActiveConfig(*this, display, mode);
+    postMessageSync(msg);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::clearAnimationFrameStats() {
+    Mutex::Autolock _l(mStateLock);
+    mAnimFrameTracker.clearStats();
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::getAnimationFrameStats(FrameStats* outStats) const {
+    Mutex::Autolock _l(mStateLock);
+    mAnimFrameTracker.getStats(outStats);
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::getHdrCapabilities(const sp<IBinder>& /*display*/,
+        HdrCapabilities* outCapabilities) const {
+    // HWC1 does not provide HDR capabilities
+    *outCapabilities = HdrCapabilities();
+    return NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+
+sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection() {
+    return mEventThread->createEventConnection();
+}
+
+// ----------------------------------------------------------------------------
+
+void SurfaceFlinger::waitForEvent() {
+    mEventQueue.waitMessage();
+}
+
+void SurfaceFlinger::signalTransaction() {
+    mEventQueue.invalidate();
+}
+
+void SurfaceFlinger::signalLayerUpdate() {
+    mEventQueue.invalidate();
+}
+
+void SurfaceFlinger::signalRefresh() {
+    mEventQueue.refresh();
+}
+
+status_t SurfaceFlinger::postMessageAsync(const sp<MessageBase>& msg,
+        nsecs_t reltime, uint32_t /* flags */) {
+    return mEventQueue.postMessage(msg, reltime);
+}
+
+status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
+        nsecs_t reltime, uint32_t /* flags */) {
+    status_t res = mEventQueue.postMessage(msg, reltime);
+    if (res == NO_ERROR) {
+        msg->wait();
+    }
+    return res;
+}
+
+void SurfaceFlinger::run() {
+    do {
+        waitForEvent();
+    } while (true);
+}
+
+void SurfaceFlinger::enableHardwareVsync() {
+    Mutex::Autolock _l(mHWVsyncLock);
+    if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
+        mPrimaryDispSync.beginResync();
+        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
+        mEventControlThread->setVsyncEnabled(true);
+        mPrimaryHWVsyncEnabled = true;
+    }
+}
+
+void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
+    Mutex::Autolock _l(mHWVsyncLock);
+
+    if (makeAvailable) {
+        mHWVsyncAvailable = true;
+    } else if (!mHWVsyncAvailable) {
+        // Hardware vsync is not currently available, so abort the resync
+        // attempt for now
+        return;
+    }
+
+    const nsecs_t period =
+            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+
+    mPrimaryDispSync.reset();
+    mPrimaryDispSync.setPeriod(period);
+
+    if (!mPrimaryHWVsyncEnabled) {
+        mPrimaryDispSync.beginResync();
+        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
+        mEventControlThread->setVsyncEnabled(true);
+        mPrimaryHWVsyncEnabled = true;
+    }
+}
+
+void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
+    Mutex::Autolock _l(mHWVsyncLock);
+    if (mPrimaryHWVsyncEnabled) {
+        //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
+        mEventControlThread->setVsyncEnabled(false);
+        mPrimaryDispSync.endResync();
+        mPrimaryHWVsyncEnabled = false;
+    }
+    if (makeUnavailable) {
+        mHWVsyncAvailable = false;
+    }
+}
+
+void SurfaceFlinger::resyncWithRateLimit() {
+    static constexpr nsecs_t kIgnoreDelay = ms2ns(500);
+    if (systemTime() - mLastSwapTime > kIgnoreDelay) {
+        resyncToHardwareVsync(false);
+    }
+}
+
+void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) {
+    bool needsHwVsync = false;
+
+    { // Scope for the lock
+        Mutex::Autolock _l(mHWVsyncLock);
+        if (type == 0 && mPrimaryHWVsyncEnabled) {
+            needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
+        }
+    }
+
+    if (needsHwVsync) {
+        enableHardwareVsync();
+    } else {
+        disableHardwareVsync(false);
+    }
+}
+
+void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
+    if (mEventThread == NULL) {
+        // This is a temporary workaround for b/7145521.  A non-null pointer
+        // does not mean EventThread has finished initializing, so this
+        // is not a correct fix.
+        ALOGW("WARNING: EventThread not started, ignoring hotplug");
+        return;
+    }
+
+    if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        Mutex::Autolock _l(mStateLock);
+        if (connected) {
+            createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
+        } else {
+            mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
+            mBuiltinDisplays[type].clear();
+        }
+        setTransactionFlags(eDisplayTransactionNeeded);
+
+        // Defer EventThread notification until SF has updated mDisplays.
+    }
+}
+
+void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
+    ATRACE_CALL();
+    getHwComposer().eventControl(disp, event, enabled);
+}
+
+void SurfaceFlinger::onMessageReceived(int32_t what) {
+    ATRACE_CALL();
+    switch (what) {
+        case MessageQueue::TRANSACTION: {
+            handleMessageTransaction();
+            break;
+        }
+        case MessageQueue::INVALIDATE: {
+            bool refreshNeeded = handleMessageTransaction();
+            refreshNeeded |= handleMessageInvalidate();
+            refreshNeeded |= mRepaintEverything;
+            if (refreshNeeded) {
+                // Signal a refresh if a transaction modified the window state,
+                // a new buffer was latched, or if HWC has requested a full
+                // repaint
+                signalRefresh();
+            }
+            break;
+        }
+        case MessageQueue::REFRESH: {
+            handleMessageRefresh();
+            break;
+        }
+    }
+}
+
+bool SurfaceFlinger::handleMessageTransaction() {
+    uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
+    if (transactionFlags) {
+        handleTransaction(transactionFlags);
+        return true;
+    }
+    return false;
+}
+
+bool SurfaceFlinger::handleMessageInvalidate() {
+    ATRACE_CALL();
+    return handlePageFlip();
+}
+
+void SurfaceFlinger::handleMessageRefresh() {
+    ATRACE_CALL();
+
+#ifdef ENABLE_FENCE_TRACKING
+    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
+#else
+    nsecs_t refreshStartTime = 0;
+#endif
+    static nsecs_t previousExpectedPresent = 0;
+    nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
+    static bool previousFrameMissed = false;
+    bool frameMissed = (expectedPresent == previousExpectedPresent);
+    if (frameMissed != previousFrameMissed) {
+        ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
+    }
+    previousFrameMissed = frameMissed;
+
+    if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) {
+        // Latch buffers, but don't send anything to HWC, then signal another
+        // wakeup for the next vsync
+        preComposition();
+        repaintEverything();
+    } else {
+        preComposition();
+        rebuildLayerStacks();
+        setUpHWComposer();
+        doDebugFlashRegions();
+        doComposition();
+        postComposition(refreshStartTime);
+    }
+
+    previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
+}
+
+void SurfaceFlinger::doDebugFlashRegions()
+{
+    // is debugging enabled
+    if (CC_LIKELY(!mDebugRegion))
+        return;
+
+    const bool repaintEverything = mRepaintEverything;
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        const sp<DisplayDevice>& hw(mDisplays[dpy]);
+        if (hw->isDisplayOn()) {
+            // transform the dirty region into this screen's coordinate space
+            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+            if (!dirtyRegion.isEmpty()) {
+                // redraw the whole screen
+                doComposeSurfaces(hw, Region(hw->bounds()));
+
+                // and draw the dirty region
+                const int32_t height = hw->getHeight();
+                RenderEngine& engine(getRenderEngine());
+                engine.fillRegionWithColor(dirtyRegion, height, 1, 0, 1, 1);
+
+                hw->compositionComplete();
+                hw->swapBuffers(getHwComposer());
+            }
+        }
+    }
+
+    postFramebuffer();
+
+    if (mDebugRegion > 1) {
+        usleep(mDebugRegion * 1000);
+    }
+
+    HWComposer& hwc(getHwComposer());
+    if (hwc.initCheck() == NO_ERROR) {
+        status_t err = hwc.prepare();
+        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+    }
+}
+
+void SurfaceFlinger::preComposition()
+{
+    bool needExtraInvalidate = false;
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        if (layers[i]->onPreComposition()) {
+            needExtraInvalidate = true;
+        }
+    }
+    if (needExtraInvalidate) {
+        signalLayerUpdate();
+    }
+}
+
+#ifdef ENABLE_FENCE_TRACKING
+void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+#else
+void SurfaceFlinger::postComposition(nsecs_t /*refreshStartTime*/)
+#endif
+{
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        layers[i]->onPostComposition();
+    }
+
+    const HWComposer& hwc = getHwComposer();
+    sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
+
+    if (presentFence->isValid()) {
+        if (mPrimaryDispSync.addPresentFence(presentFence)) {
+            enableHardwareVsync();
+        } else {
+            disableHardwareVsync(false);
+        }
+    }
+
+    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    if (kIgnorePresentFences) {
+        if (hw->isDisplayOn()) {
+            enableHardwareVsync();
+        }
+    }
+
+#ifdef ENABLE_FENCE_TRACKING
+    mFenceTracker.addFrame(refreshStartTime, presentFence,
+            hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
+#endif
+
+    if (mAnimCompositionPending) {
+        mAnimCompositionPending = false;
+
+        if (presentFence->isValid()) {
+            mAnimFrameTracker.setActualPresentFence(presentFence);
+        } else {
+            // The HWC doesn't support present fences, so use the refresh
+            // timestamp instead.
+            nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
+            mAnimFrameTracker.setActualPresentTime(presentTime);
+        }
+        mAnimFrameTracker.advanceFrame();
+    }
+
+    if (hw->getPowerMode() == HWC_POWER_MODE_OFF) {
+        return;
+    }
+
+    nsecs_t currentTime = systemTime();
+    if (mHasPoweredOff) {
+        mHasPoweredOff = false;
+    } else {
+        nsecs_t period = mPrimaryDispSync.getPeriod();
+        nsecs_t elapsedTime = currentTime - mLastSwapTime;
+        size_t numPeriods = static_cast<size_t>(elapsedTime / period);
+        if (numPeriods < NUM_BUCKETS - 1) {
+            mFrameBuckets[numPeriods] += elapsedTime;
+        } else {
+            mFrameBuckets[NUM_BUCKETS - 1] += elapsedTime;
+        }
+        mTotalTime += elapsedTime;
+    }
+    mLastSwapTime = currentTime;
+}
+
+void SurfaceFlinger::rebuildLayerStacks() {
+    // rebuild the visible layer list per screen
+    if (CC_UNLIKELY(mVisibleRegionsDirty)) {
+        ATRACE_CALL();
+        mVisibleRegionsDirty = false;
+        invalidateHwcGeometry();
+
+        const LayerVector& layers(mDrawingState.layersSortedByZ);
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            Region opaqueRegion;
+            Region dirtyRegion;
+            Vector< sp<Layer> > layersSortedByZ;
+            const sp<DisplayDevice>& hw(mDisplays[dpy]);
+            const Transform& tr(hw->getTransform());
+            const Rect bounds(hw->getBounds());
+            if (hw->isDisplayOn()) {
+                SurfaceFlinger::computeVisibleRegions(layers,
+                        hw->getLayerStack(), dirtyRegion, opaqueRegion);
+
+                const size_t count = layers.size();
+                for (size_t i=0 ; i<count ; i++) {
+                    const sp<Layer>& layer(layers[i]);
+                    const Layer::State& s(layer->getDrawingState());
+                    if (s.layerStack == hw->getLayerStack()) {
+                        Region drawRegion(tr.transform(
+                                layer->visibleNonTransparentRegion));
+                        drawRegion.andSelf(bounds);
+                        if (!drawRegion.isEmpty()) {
+                            layersSortedByZ.add(layer);
+                        }
+                    }
+                }
+            }
+            hw->setVisibleLayersSortedByZ(layersSortedByZ);
+            hw->undefinedRegion.set(bounds);
+            hw->undefinedRegion.subtractSelf(tr.transform(opaqueRegion));
+            hw->dirtyRegion.orSelf(dirtyRegion);
+        }
+    }
+}
+
+void SurfaceFlinger::setUpHWComposer() {
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        bool dirty = !mDisplays[dpy]->getDirtyRegion(false).isEmpty();
+        bool empty = mDisplays[dpy]->getVisibleLayersSortedByZ().size() == 0;
+        bool wasEmpty = !mDisplays[dpy]->lastCompositionHadVisibleLayers;
+
+        // If nothing has changed (!dirty), don't recompose.
+        // If something changed, but we don't currently have any visible layers,
+        //   and didn't when we last did a composition, then skip it this time.
+        // The second rule does two things:
+        // - When all layers are removed from a display, we'll emit one black
+        //   frame, then nothing more until we get new layers.
+        // - When a display is created with a private layer stack, we won't
+        //   emit any black frames until a layer is added to the layer stack.
+        bool mustRecompose = dirty && !(empty && wasEmpty);
+
+        ALOGV_IF(mDisplays[dpy]->getDisplayType() == DisplayDevice::DISPLAY_VIRTUAL,
+                "dpy[%zu]: %s composition (%sdirty %sempty %swasEmpty)", dpy,
+                mustRecompose ? "doing" : "skipping",
+                dirty ? "+" : "-",
+                empty ? "+" : "-",
+                wasEmpty ? "+" : "-");
+
+        mDisplays[dpy]->beginFrame(mustRecompose);
+
+        if (mustRecompose) {
+            mDisplays[dpy]->lastCompositionHadVisibleLayers = !empty;
+        }
+    }
+
+    HWComposer& hwc(getHwComposer());
+    if (hwc.initCheck() == NO_ERROR) {
+        // build the h/w work list
+        if (CC_UNLIKELY(mHwWorkListDirty)) {
+            mHwWorkListDirty = false;
+            for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+                sp<const DisplayDevice> hw(mDisplays[dpy]);
+                const int32_t id = hw->getHwcDisplayId();
+                if (id >= 0) {
+                    const Vector< sp<Layer> >& currentLayers(
+                        hw->getVisibleLayersSortedByZ());
+                    const size_t count = currentLayers.size();
+                    if (hwc.createWorkList(id, count) == NO_ERROR) {
+                        HWComposer::LayerListIterator cur = hwc.begin(id);
+                        const HWComposer::LayerListIterator end = hwc.end(id);
+                        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+                            const sp<Layer>& layer(currentLayers[i]);
+                            layer->setGeometry(hw, *cur);
+                            if (mDebugDisableHWC || mDebugRegion || mDaltonize || mHasColorMatrix) {
+                                cur->setSkip(true);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // set the per-frame data
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            sp<const DisplayDevice> hw(mDisplays[dpy]);
+            const int32_t id = hw->getHwcDisplayId();
+            if (id >= 0) {
+                const Vector< sp<Layer> >& currentLayers(
+                    hw->getVisibleLayersSortedByZ());
+                const size_t count = currentLayers.size();
+                HWComposer::LayerListIterator cur = hwc.begin(id);
+                const HWComposer::LayerListIterator end = hwc.end(id);
+                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+                    /*
+                     * update the per-frame h/w composer data for each layer
+                     * and build the transparent region of the FB
+                     */
+                    const sp<Layer>& layer(currentLayers[i]);
+                    layer->setPerFrameData(hw, *cur);
+                }
+            }
+        }
+
+        // If possible, attempt to use the cursor overlay on each display.
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            sp<const DisplayDevice> hw(mDisplays[dpy]);
+            const int32_t id = hw->getHwcDisplayId();
+            if (id >= 0) {
+                const Vector< sp<Layer> >& currentLayers(
+                    hw->getVisibleLayersSortedByZ());
+                const size_t count = currentLayers.size();
+                HWComposer::LayerListIterator cur = hwc.begin(id);
+                const HWComposer::LayerListIterator end = hwc.end(id);
+                for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+                    const sp<Layer>& layer(currentLayers[i]);
+                    if (layer->isPotentialCursor()) {
+                        cur->setIsCursorLayerHint();
+                        break;
+                    }
+                }
+            }
+        }
+
+        status_t err = hwc.prepare();
+        ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+
+        for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+            sp<const DisplayDevice> hw(mDisplays[dpy]);
+            hw->prepareFrame(hwc);
+        }
+    }
+}
+
+void SurfaceFlinger::doComposition() {
+    ATRACE_CALL();
+    const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        const sp<DisplayDevice>& hw(mDisplays[dpy]);
+        if (hw->isDisplayOn()) {
+            // transform the dirty region into this screen's coordinate space
+            const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
+
+            // repaint the framebuffer (if needed)
+            doDisplayComposition(hw, dirtyRegion);
+
+            hw->dirtyRegion.clear();
+            hw->flip(hw->swapRegion);
+            hw->swapRegion.clear();
+        }
+        // inform the h/w that we're done compositing
+        hw->compositionComplete();
+    }
+    postFramebuffer();
+}
+
+void SurfaceFlinger::postFramebuffer()
+{
+    ATRACE_CALL();
+
+    const nsecs_t now = systemTime();
+    mDebugInSwapBuffers = now;
+
+    HWComposer& hwc(getHwComposer());
+    if (hwc.initCheck() == NO_ERROR) {
+        if (!hwc.supportsFramebufferTarget()) {
+            // EGL spec says:
+            //   "surface must be bound to the calling thread's current context,
+            //    for the current rendering API."
+            getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+        }
+        hwc.commit();
+    }
+
+    // make the default display current because the VirtualDisplayDevice code cannot
+    // deal with dequeueBuffer() being called outside of the composition loop; however
+    // the code below can call glFlush() which is allowed (and does in some case) call
+    // dequeueBuffer().
+    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
+
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        sp<const DisplayDevice> hw(mDisplays[dpy]);
+        const Vector< sp<Layer> >& currentLayers(hw->getVisibleLayersSortedByZ());
+        hw->onSwapBuffersCompleted(hwc);
+        const size_t count = currentLayers.size();
+        int32_t id = hw->getHwcDisplayId();
+        if (id >=0 && hwc.initCheck() == NO_ERROR) {
+            HWComposer::LayerListIterator cur = hwc.begin(id);
+            const HWComposer::LayerListIterator end = hwc.end(id);
+            for (size_t i = 0; cur != end && i < count; ++i, ++cur) {
+                currentLayers[i]->onLayerDisplayed(hw, &*cur);
+            }
+        } else {
+            for (size_t i = 0; i < count; i++) {
+                currentLayers[i]->onLayerDisplayed(hw, NULL);
+            }
+        }
+    }
+
+    mLastSwapBufferTime = systemTime() - now;
+    mDebugInSwapBuffers = 0;
+
+    uint32_t flipCount = getDefaultDisplayDevice()->getPageFlipCount();
+    if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
+        logFrameStats();
+    }
+}
+
+void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
+{
+    ATRACE_CALL();
+
+    // here we keep a copy of the drawing state (that is the state that's
+    // going to be overwritten by handleTransactionLocked()) outside of
+    // mStateLock so that the side-effects of the State assignment
+    // don't happen with mStateLock held (which can cause deadlocks).
+    State drawingState(mDrawingState);
+
+    Mutex::Autolock _l(mStateLock);
+    const nsecs_t now = systemTime();
+    mDebugInTransaction = now;
+
+    // Here we're guaranteed that some transaction flags are set
+    // so we can call handleTransactionLocked() unconditionally.
+    // We call getTransactionFlags(), which will also clear the flags,
+    // with mStateLock held to guarantee that mCurrentState won't change
+    // until the transaction is committed.
+
+    transactionFlags = getTransactionFlags(eTransactionMask);
+    handleTransactionLocked(transactionFlags);
+
+    mLastTransactionTime = systemTime() - now;
+    mDebugInTransaction = 0;
+    invalidateHwcGeometry();
+    // here the transaction has been committed
+}
+
+void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
+{
+    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
+    const size_t count = currentLayers.size();
+
+    // Notify all layers of available frames
+    for (size_t i = 0; i < count; ++i) {
+        currentLayers[i]->notifyAvailableFrames();
+    }
+
+    /*
+     * Traversal of the children
+     * (perform the transaction for each of them if needed)
+     */
+
+    if (transactionFlags & eTraversalNeeded) {
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<Layer>& layer(currentLayers[i]);
+            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
+            if (!trFlags) continue;
+
+            const uint32_t flags = layer->doTransaction(0);
+            if (flags & Layer::eVisibleRegion)
+                mVisibleRegionsDirty = true;
+        }
+    }
+
+    /*
+     * Perform display own transactions if needed
+     */
+
+    if (transactionFlags & eDisplayTransactionNeeded) {
+        // here we take advantage of Vector's copy-on-write semantics to
+        // improve performance by skipping the transaction entirely when
+        // know that the lists are identical
+        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
+        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
+        if (!curr.isIdenticalTo(draw)) {
+            mVisibleRegionsDirty = true;
+            const size_t cc = curr.size();
+                  size_t dc = draw.size();
+
+            // find the displays that were removed
+            // (ie: in drawing state but not in current state)
+            // also handle displays that changed
+            // (ie: displays that are in both lists)
+            for (size_t i=0 ; i<dc ; i++) {
+                const ssize_t j = curr.indexOfKey(draw.keyAt(i));
+                if (j < 0) {
+                    // in drawing state but not in current state
+                    if (!draw[i].isMainDisplay()) {
+                        // Call makeCurrent() on the primary display so we can
+                        // be sure that nothing associated with this display
+                        // is current.
+                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDevice());
+                        defaultDisplay->makeCurrent(mEGLDisplay, mEGLContext);
+                        sp<DisplayDevice> hw(getDisplayDevice(draw.keyAt(i)));
+                        if (hw != NULL)
+                            hw->disconnect(getHwComposer());
+                        if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
+                            mEventThread->onHotplugReceived(draw[i].type, false);
+                        mDisplays.removeItem(draw.keyAt(i));
+                    } else {
+                        ALOGW("trying to remove the main display");
+                    }
+                } else {
+                    // this display is in both lists. see if something changed.
+                    const DisplayDeviceState& state(curr[j]);
+                    const wp<IBinder>& display(curr.keyAt(j));
+                    const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
+                    const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
+                    if (state_binder != draw_binder) {
+                        // changing the surface is like destroying and
+                        // recreating the DisplayDevice, so we just remove it
+                        // from the drawing state, so that it get re-added
+                        // below.
+                        sp<DisplayDevice> hw(getDisplayDevice(display));
+                        if (hw != NULL)
+                            hw->disconnect(getHwComposer());
+                        mDisplays.removeItem(display);
+                        mDrawingState.displays.removeItemsAt(i);
+                        dc--; i--;
+                        // at this point we must loop to the next item
+                        continue;
+                    }
+
+                    const sp<DisplayDevice> disp(getDisplayDevice(display));
+                    if (disp != NULL) {
+                        if (state.layerStack != draw[i].layerStack) {
+                            disp->setLayerStack(state.layerStack);
+                        }
+                        if ((state.orientation != draw[i].orientation)
+                                || (state.viewport != draw[i].viewport)
+                                || (state.frame != draw[i].frame))
+                        {
+                            disp->setProjection(state.orientation,
+                                    state.viewport, state.frame);
+                        }
+                        if (state.width != draw[i].width || state.height != draw[i].height) {
+                            disp->setDisplaySize(state.width, state.height);
+                        }
+                    }
+                }
+            }
+
+            // find displays that were added
+            // (ie: in current state but not in drawing state)
+            for (size_t i=0 ; i<cc ; i++) {
+                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
+                    const DisplayDeviceState& state(curr[i]);
+
+                    sp<DisplaySurface> dispSurface;
+                    sp<IGraphicBufferProducer> producer;
+                    sp<IGraphicBufferProducer> bqProducer;
+                    sp<IGraphicBufferConsumer> bqConsumer;
+                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
+                            new GraphicBufferAlloc());
+
+                    int32_t hwcDisplayId = -1;
+                    if (state.isVirtualDisplay()) {
+                        // Virtual displays without a surface are dormant:
+                        // they have external state (layer stack, projection,
+                        // etc.) but no internal state (i.e. a DisplayDevice).
+                        if (state.surface != NULL) {
+
+                            int width = 0;
+                            int status = state.surface->query(
+                                    NATIVE_WINDOW_WIDTH, &width);
+                            ALOGE_IF(status != NO_ERROR,
+                                    "Unable to query width (%d)", status);
+                            int height = 0;
+                            status = state.surface->query(
+                                    NATIVE_WINDOW_HEIGHT, &height);
+                            ALOGE_IF(status != NO_ERROR,
+                                    "Unable to query height (%d)", status);
+                            if (MAX_VIRTUAL_DISPLAY_DIMENSION == 0 ||
+                                    (width <= MAX_VIRTUAL_DISPLAY_DIMENSION &&
+                                     height <= MAX_VIRTUAL_DISPLAY_DIMENSION)) {
+                                hwcDisplayId = allocateHwcDisplayId(state.type);
+                            }
+
+                            sp<VirtualDisplaySurface> vds = new VirtualDisplaySurface(
+                                    *mHwc, hwcDisplayId, state.surface,
+                                    bqProducer, bqConsumer, state.displayName);
+
+                            dispSurface = vds;
+                            producer = vds;
+                        }
+                    } else {
+                        ALOGE_IF(state.surface!=NULL,
+                                "adding a supported display, but rendering "
+                                "surface is provided (%p), ignoring it",
+                                state.surface.get());
+                        hwcDisplayId = allocateHwcDisplayId(state.type);
+                        // for supported (by hwc) displays we provide our
+                        // own rendering surface
+                        dispSurface = new FramebufferSurface(*mHwc, state.type,
+                                bqConsumer);
+                        producer = bqProducer;
+                    }
+
+                    const wp<IBinder>& display(curr.keyAt(i));
+                    if (dispSurface != NULL) {
+                        sp<DisplayDevice> hw = new DisplayDevice(this,
+                                state.type, hwcDisplayId,
+                                mHwc->getFormat(hwcDisplayId), state.isSecure,
+                                display, dispSurface, producer,
+                                mRenderEngine->getEGLConfig());
+                        hw->setLayerStack(state.layerStack);
+                        hw->setProjection(state.orientation,
+                                state.viewport, state.frame);
+                        hw->setDisplayName(state.displayName);
+                        mDisplays.add(display, hw);
+                        if (state.isVirtualDisplay()) {
+                            if (hwcDisplayId >= 0) {
+                                mHwc->setVirtualDisplayProperties(hwcDisplayId,
+                                        hw->getWidth(), hw->getHeight(),
+                                        hw->getFormat());
+                            }
+                        } else {
+                            mEventThread->onHotplugReceived(state.type, true);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (transactionFlags & (eTraversalNeeded|eDisplayTransactionNeeded)) {
+        // The transform hint might have changed for some layers
+        // (either because a display has changed, or because a layer
+        // as changed).
+        //
+        // Walk through all the layers in currentLayers,
+        // and update their transform hint.
+        //
+        // If a layer is visible only on a single display, then that
+        // display is used to calculate the hint, otherwise we use the
+        // default display.
+        //
+        // NOTE: we do this here, rather than in rebuildLayerStacks() so that
+        // the hint is set before we acquire a buffer from the surface texture.
+        //
+        // NOTE: layer transactions have taken place already, so we use their
+        // drawing state. However, SurfaceFlinger's own transaction has not
+        // happened yet, so we must use the current state layer list
+        // (soon to become the drawing state list).
+        //
+        sp<const DisplayDevice> disp;
+        uint32_t currentlayerStack = 0;
+        for (size_t i=0; i<count; i++) {
+            // NOTE: we rely on the fact that layers are sorted by
+            // layerStack first (so we don't have to traverse the list
+            // of displays for every layer).
+            const sp<Layer>& layer(currentLayers[i]);
+            uint32_t layerStack = layer->getDrawingState().layerStack;
+            if (i==0 || currentlayerStack != layerStack) {
+                currentlayerStack = layerStack;
+                // figure out if this layerstack is mirrored
+                // (more than one display) if so, pick the default display,
+                // if not, pick the only display it's on.
+                disp.clear();
+                for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+                    sp<const DisplayDevice> hw(mDisplays[dpy]);
+                    if (hw->getLayerStack() == currentlayerStack) {
+                        if (disp == NULL) {
+                            disp = hw;
+                        } else {
+                            disp = NULL;
+                            break;
+                        }
+                    }
+                }
+            }
+            if (disp == NULL) {
+                // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
+                // redraw after transform hint changes. See bug 8508397.
+
+                // could be null when this layer is using a layerStack
+                // that is not visible on any display. Also can occur at
+                // screen off/on times.
+                disp = getDefaultDisplayDevice();
+            }
+            layer->updateTransformHint(disp);
+        }
+    }
+
+
+    /*
+     * Perform our own transaction if needed
+     */
+
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    if (currentLayers.size() > layers.size()) {
+        // layers have been added
+        mVisibleRegionsDirty = true;
+    }
+
+    // some layers might have been removed, so
+    // we need to update the regions they're exposing.
+    if (mLayersRemoved) {
+        mLayersRemoved = false;
+        mVisibleRegionsDirty = true;
+        const size_t count = layers.size();
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<Layer>& layer(layers[i]);
+            if (currentLayers.indexOf(layer) < 0) {
+                // this layer is not visible anymore
+                // TODO: we could traverse the tree from front to back and
+                //       compute the actual visible region
+                // TODO: we could cache the transformed region
+                const Layer::State& s(layer->getDrawingState());
+                Region visibleReg = s.active.transform.transform(
+                        Region(Rect(s.active.w, s.active.h)));
+                invalidateLayerStack(s.layerStack, visibleReg);
+            }
+        }
+    }
+
+    commitTransaction();
+
+    updateCursorAsync();
+}
+
+void SurfaceFlinger::updateCursorAsync()
+{
+    HWComposer& hwc(getHwComposer());
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        sp<const DisplayDevice> hw(mDisplays[dpy]);
+        const int32_t id = hw->getHwcDisplayId();
+        if (id < 0) {
+            continue;
+        }
+        const Vector< sp<Layer> >& currentLayers(
+            hw->getVisibleLayersSortedByZ());
+        const size_t count = currentLayers.size();
+        HWComposer::LayerListIterator cur = hwc.begin(id);
+        const HWComposer::LayerListIterator end = hwc.end(id);
+        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+            if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
+                continue;
+            }
+            const sp<Layer>& layer(currentLayers[i]);
+            Rect cursorPos = layer->getPosition(hw);
+            hwc.setCursorPositionAsync(id, cursorPos);
+            break;
+        }
+    }
+}
+
+void SurfaceFlinger::commitTransaction()
+{
+    if (!mLayersPendingRemoval.isEmpty()) {
+        // Notify removed layers now that they can't be drawn from
+        for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
+            mLayersPendingRemoval[i]->onRemoved();
+        }
+        mLayersPendingRemoval.clear();
+    }
+
+    // If this transaction is part of a window animation then the next frame
+    // we composite should be considered an animation as well.
+    mAnimCompositionPending = mAnimTransactionPending;
+
+    mDrawingState = mCurrentState;
+    mTransactionPending = false;
+    mAnimTransactionPending = false;
+    mTransactionCV.broadcast();
+}
+
+void SurfaceFlinger::computeVisibleRegions(
+        const LayerVector& currentLayers, uint32_t layerStack,
+        Region& outDirtyRegion, Region& outOpaqueRegion)
+{
+    ATRACE_CALL();
+
+    Region aboveOpaqueLayers;
+    Region aboveCoveredLayers;
+    Region dirty;
+
+    outDirtyRegion.clear();
+
+    size_t i = currentLayers.size();
+    while (i--) {
+        const sp<Layer>& layer = currentLayers[i];
+
+        // start with the whole surface at its current location
+        const Layer::State& s(layer->getDrawingState());
+
+        // only consider the layers on the given layer stack
+        if (s.layerStack != layerStack)
+            continue;
+
+        /*
+         * opaqueRegion: area of a surface that is fully opaque.
+         */
+        Region opaqueRegion;
+
+        /*
+         * visibleRegion: area of a surface that is visible on screen
+         * and not fully transparent. This is essentially the layer's
+         * footprint minus the opaque regions above it.
+         * Areas covered by a translucent surface are considered visible.
+         */
+        Region visibleRegion;
+
+        /*
+         * coveredRegion: area of a surface that is covered by all
+         * visible regions above it (which includes the translucent areas).
+         */
+        Region coveredRegion;
+
+        /*
+         * transparentRegion: area of a surface that is hinted to be completely
+         * transparent. This is only used to tell when the layer has no visible
+         * non-transparent regions and can be removed from the layer list. It
+         * does not affect the visibleRegion of this layer or any layers
+         * beneath it. The hint may not be correct if apps don't respect the
+         * SurfaceView restrictions (which, sadly, some don't).
+         */
+        Region transparentRegion;
+
+
+        // handle hidden surfaces by setting the visible region to empty
+        if (CC_LIKELY(layer->isVisible())) {
+            const bool translucent = !layer->isOpaque(s);
+            Rect bounds(s.active.transform.transform(layer->computeBounds()));
+            visibleRegion.set(bounds);
+            if (!visibleRegion.isEmpty()) {
+                // Remove the transparent area from the visible region
+                if (translucent) {
+                    const Transform tr(s.active.transform);
+                    if (tr.transformed()) {
+                        if (tr.preserveRects()) {
+                            // transform the transparent region
+                            transparentRegion = tr.transform(s.activeTransparentRegion);
+                        } else {
+                            // transformation too complex, can't do the
+                            // transparent region optimization.
+                            transparentRegion.clear();
+                        }
+                    } else {
+                        transparentRegion = s.activeTransparentRegion;
+                    }
+                }
+
+                // compute the opaque region
+                const int32_t layerOrientation = s.active.transform.getOrientation();
+                if (s.alpha==255 && !translucent &&
+                        ((layerOrientation & Transform::ROT_INVALID) == false)) {
+                    // the opaque region is the layer's footprint
+                    opaqueRegion = visibleRegion;
+                }
+            }
+        }
+
+        // Clip the covered region to the visible region
+        coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
+
+        // Update aboveCoveredLayers for next (lower) layer
+        aboveCoveredLayers.orSelf(visibleRegion);
+
+        // subtract the opaque region covered by the layers above us
+        visibleRegion.subtractSelf(aboveOpaqueLayers);
+
+        // compute this layer's dirty region
+        if (layer->contentDirty) {
+            // we need to invalidate the whole region
+            dirty = visibleRegion;
+            // as well, as the old visible region
+            dirty.orSelf(layer->visibleRegion);
+            layer->contentDirty = false;
+        } else {
+            /* compute the exposed region:
+             *   the exposed region consists of two components:
+             *   1) what's VISIBLE now and was COVERED before
+             *   2) what's EXPOSED now less what was EXPOSED before
+             *
+             * note that (1) is conservative, we start with the whole
+             * visible region but only keep what used to be covered by
+             * something -- which mean it may have been exposed.
+             *
+             * (2) handles areas that were not covered by anything but got
+             * exposed because of a resize.
+             */
+            const Region newExposed = visibleRegion - coveredRegion;
+            const Region oldVisibleRegion = layer->visibleRegion;
+            const Region oldCoveredRegion = layer->coveredRegion;
+            const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
+            dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
+        }
+        dirty.subtractSelf(aboveOpaqueLayers);
+
+        // accumulate to the screen dirty region
+        outDirtyRegion.orSelf(dirty);
+
+        // Update aboveOpaqueLayers for next (lower) layer
+        aboveOpaqueLayers.orSelf(opaqueRegion);
+
+        // Store the visible region in screen space
+        layer->setVisibleRegion(visibleRegion);
+        layer->setCoveredRegion(coveredRegion);
+        layer->setVisibleNonTransparentRegion(
+                visibleRegion.subtract(transparentRegion));
+    }
+
+    outOpaqueRegion = aboveOpaqueLayers;
+}
+
+void SurfaceFlinger::invalidateLayerStack(uint32_t layerStack,
+        const Region& dirty) {
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        const sp<DisplayDevice>& hw(mDisplays[dpy]);
+        if (hw->getLayerStack() == layerStack) {
+            hw->dirtyRegion.orSelf(dirty);
+        }
+    }
+}
+
+bool SurfaceFlinger::handlePageFlip()
+{
+    Region dirtyRegion;
+
+    bool visibleRegions = false;
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    bool frameQueued = false;
+
+    // Store the set of layers that need updates. This set must not change as
+    // buffers are being latched, as this could result in a deadlock.
+    // Example: Two producers share the same command stream and:
+    // 1.) Layer 0 is latched
+    // 2.) Layer 0 gets a new frame
+    // 2.) Layer 1 gets a new frame
+    // 3.) Layer 1 is latched.
+    // Display is now waiting on Layer 1's frame, which is behind layer 0's
+    // second frame. But layer 0's second frame could be waiting on display.
+    Vector<Layer*> layersWithQueuedFrames;
+    for (size_t i = 0, count = layers.size(); i<count ; i++) {
+        const sp<Layer>& layer(layers[i]);
+        if (layer->hasQueuedFrame()) {
+            frameQueued = true;
+            if (layer->shouldPresentNow(mPrimaryDispSync)) {
+                layersWithQueuedFrames.push_back(layer.get());
+            } else {
+                layer->useEmptyDamage();
+            }
+        } else {
+            layer->useEmptyDamage();
+        }
+    }
+    for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
+        Layer* layer = layersWithQueuedFrames[i];
+        const Region dirty(layer->latchBuffer(visibleRegions));
+        layer->useSurfaceDamage();
+        const Layer::State& s(layer->getDrawingState());
+        invalidateLayerStack(s.layerStack, dirty);
+    }
+
+    mVisibleRegionsDirty |= visibleRegions;
+
+    // If we will need to wake up at some time in the future to deal with a
+    // queued frame that shouldn't be displayed during this vsync period, wake
+    // up during the next vsync period to check again.
+    if (frameQueued && layersWithQueuedFrames.empty()) {
+        signalLayerUpdate();
+    }
+
+    // Only continue with the refresh if there is actually new work to do
+    return !layersWithQueuedFrames.empty();
+}
+
+void SurfaceFlinger::invalidateHwcGeometry()
+{
+    mHwWorkListDirty = true;
+}
+
+
+void SurfaceFlinger::doDisplayComposition(const sp<const DisplayDevice>& hw,
+        const Region& inDirtyRegion)
+{
+    // We only need to actually compose the display if:
+    // 1) It is being handled by hardware composer, which may need this to
+    //    keep its virtual display state machine in sync, or
+    // 2) There is work to be done (the dirty region isn't empty)
+    bool isHwcDisplay = hw->getHwcDisplayId() >= 0;
+    if (!isHwcDisplay && inDirtyRegion.isEmpty()) {
+        return;
+    }
+
+    Region dirtyRegion(inDirtyRegion);
+
+    // compute the invalid region
+    hw->swapRegion.orSelf(dirtyRegion);
+
+    uint32_t flags = hw->getFlags();
+    if (flags & DisplayDevice::SWAP_RECTANGLE) {
+        // we can redraw only what's dirty, but since SWAP_RECTANGLE only
+        // takes a rectangle, we must make sure to update that whole
+        // rectangle in that case
+        dirtyRegion.set(hw->swapRegion.bounds());
+    } else {
+        if (flags & DisplayDevice::PARTIAL_UPDATES) {
+            // We need to redraw the rectangle that will be updated
+            // (pushed to the framebuffer).
+            // This is needed because PARTIAL_UPDATES only takes one
+            // rectangle instead of a region (see DisplayDevice::flip())
+            dirtyRegion.set(hw->swapRegion.bounds());
+        } else {
+            // we need to redraw everything (the whole screen)
+            dirtyRegion.set(hw->bounds());
+            hw->swapRegion = dirtyRegion;
+        }
+    }
+
+    if (CC_LIKELY(!mDaltonize && !mHasColorMatrix)) {
+        if (!doComposeSurfaces(hw, dirtyRegion)) return;
+    } else {
+        RenderEngine& engine(getRenderEngine());
+        mat4 colorMatrix = mColorMatrix;
+        if (mDaltonize) {
+            colorMatrix = colorMatrix * mDaltonizer();
+        }
+        mat4 oldMatrix = engine.setupColorTransform(colorMatrix);
+        doComposeSurfaces(hw, dirtyRegion);
+        engine.setupColorTransform(oldMatrix);
+    }
+
+    // update the swap region and clear the dirty region
+    hw->swapRegion.orSelf(dirtyRegion);
+
+    // swap buffers (presentation)
+    hw->swapBuffers(getHwComposer());
+}
+
+bool SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const Region& dirty)
+{
+    RenderEngine& engine(getRenderEngine());
+    const int32_t id = hw->getHwcDisplayId();
+    HWComposer& hwc(getHwComposer());
+    HWComposer::LayerListIterator cur = hwc.begin(id);
+    const HWComposer::LayerListIterator end = hwc.end(id);
+
+    bool hasGlesComposition = hwc.hasGlesComposition(id);
+    if (hasGlesComposition) {
+        if (!hw->makeCurrent(mEGLDisplay, mEGLContext)) {
+            ALOGW("DisplayDevice::makeCurrent failed. Aborting surface composition for display %s",
+                  hw->getDisplayName().string());
+            eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+            if(!getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext)) {
+              ALOGE("DisplayDevice::makeCurrent on default display failed. Aborting.");
+            }
+            return false;
+        }
+
+        // Never touch the framebuffer if we don't have any framebuffer layers
+        const bool hasHwcComposition = hwc.hasHwcComposition(id);
+        if (hasHwcComposition) {
+            // when using overlays, we assume a fully transparent framebuffer
+            // NOTE: we could reduce how much we need to clear, for instance
+            // remove where there are opaque FB layers. however, on some
+            // GPUs doing a "clean slate" clear might be more efficient.
+            // We'll revisit later if needed.
+            engine.clearWithColor(0, 0, 0, 0);
+        } else {
+            // we start with the whole screen area
+            const Region bounds(hw->getBounds());
+
+            // we remove the scissor part
+            // we're left with the letterbox region
+            // (common case is that letterbox ends-up being empty)
+            const Region letterbox(bounds.subtract(hw->getScissor()));
+
+            // compute the area to clear
+            Region region(hw->undefinedRegion.merge(letterbox));
+
+            // but limit it to the dirty region
+            region.andSelf(dirty);
+
+            // screen is already cleared here
+            if (!region.isEmpty()) {
+                // can happen with SurfaceView
+                drawWormhole(hw, region);
+            }
+        }
+
+        if (hw->getDisplayType() != DisplayDevice::DISPLAY_PRIMARY) {
+            // just to be on the safe side, we don't set the
+            // scissor on the main display. It should never be needed
+            // anyways (though in theory it could since the API allows it).
+            const Rect& bounds(hw->getBounds());
+            const Rect& scissor(hw->getScissor());
+            if (scissor != bounds) {
+                // scissor doesn't match the screen's dimensions, so we
+                // need to clear everything outside of it and enable
+                // the GL scissor so we don't draw anything where we shouldn't
+
+                // enable scissor for this frame
+                const uint32_t height = hw->getHeight();
+                engine.setScissor(scissor.left, height - scissor.bottom,
+                        scissor.getWidth(), scissor.getHeight());
+            }
+        }
+    }
+
+    /*
+     * and then, render the layers targeted at the framebuffer
+     */
+
+    const Vector< sp<Layer> >& layers(hw->getVisibleLayersSortedByZ());
+    const size_t count = layers.size();
+    const Transform& tr = hw->getTransform();
+    if (cur != end) {
+        // we're using h/w composer
+        for (size_t i=0 ; i<count && cur!=end ; ++i, ++cur) {
+            const sp<Layer>& layer(layers[i]);
+            const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
+            if (!clip.isEmpty()) {
+                switch (cur->getCompositionType()) {
+                    case HWC_CURSOR_OVERLAY:
+                    case HWC_OVERLAY: {
+                        const Layer::State& state(layer->getDrawingState());
+                        if ((cur->getHints() & HWC_HINT_CLEAR_FB)
+                                && i
+                                && layer->isOpaque(state) && (state.alpha == 0xFF)
+                                && hasGlesComposition) {
+                            // never clear the very first layer since we're
+                            // guaranteed the FB is already cleared
+                            layer->clearWithOpenGL(hw, clip);
+                        }
+                        break;
+                    }
+                    case HWC_FRAMEBUFFER: {
+                        layer->draw(hw, clip);
+                        break;
+                    }
+                    case HWC_FRAMEBUFFER_TARGET: {
+                        // this should not happen as the iterator shouldn't
+                        // let us get there.
+                        ALOGW("HWC_FRAMEBUFFER_TARGET found in hwc list (index=%zu)", i);
+                        break;
+                    }
+                }
+            }
+            layer->setAcquireFence(hw, *cur);
+        }
+    } else {
+        // we're not using h/w composer
+        for (size_t i=0 ; i<count ; ++i) {
+            const sp<Layer>& layer(layers[i]);
+            const Region clip(dirty.intersect(
+                    tr.transform(layer->visibleRegion)));
+            if (!clip.isEmpty()) {
+                layer->draw(hw, clip);
+            }
+        }
+    }
+
+    // disable scissor at the end of the frame
+    engine.disableScissor();
+    return true;
+}
+
+void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, const Region& region) const {
+    const int32_t height = hw->getHeight();
+    RenderEngine& engine(getRenderEngine());
+    engine.fillRegionWithColor(region, height, 0, 0, 0, 0);
+}
+
+status_t SurfaceFlinger::addClientLayer(const sp<Client>& client,
+        const sp<IBinder>& handle,
+        const sp<IGraphicBufferProducer>& gbc,
+        const sp<Layer>& lbc)
+{
+    // add this layer to the current state list
+    {
+        Mutex::Autolock _l(mStateLock);
+        if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) {
+            return NO_MEMORY;
+        }
+        mCurrentState.layersSortedByZ.add(lbc);
+        mGraphicBufferProducerList.add(IInterface::asBinder(gbc));
+    }
+
+    // attach this layer to the client
+    client->attachLayer(handle, lbc);
+
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::removeLayer(const sp<Layer>& layer) {
+    Mutex::Autolock _l(mStateLock);
+    ssize_t index = mCurrentState.layersSortedByZ.remove(layer);
+    if (index >= 0) {
+        mLayersPendingRemoval.push(layer);
+        mLayersRemoved = true;
+        setTransactionFlags(eTransactionNeeded);
+        return NO_ERROR;
+    }
+    return status_t(index);
+}
+
+uint32_t SurfaceFlinger::peekTransactionFlags(uint32_t /* flags */) {
+    return android_atomic_release_load(&mTransactionFlags);
+}
+
+uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags) {
+    return android_atomic_and(~flags, &mTransactionFlags) & flags;
+}
+
+uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags) {
+    uint32_t old = android_atomic_or(flags, &mTransactionFlags);
+    if ((old & flags)==0) { // wake the server up
+        signalTransaction();
+    }
+    return old;
+}
+
+void SurfaceFlinger::setTransactionState(
+        const Vector<ComposerState>& state,
+        const Vector<DisplayState>& displays,
+        uint32_t flags)
+{
+    ATRACE_CALL();
+    Mutex::Autolock _l(mStateLock);
+    uint32_t transactionFlags = 0;
+
+    if (flags & eAnimation) {
+        // For window updates that are part of an animation we must wait for
+        // previous animation "frames" to be handled.
+        while (mAnimTransactionPending) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                // just in case something goes wrong in SF, return to the
+                // caller after a few seconds.
+                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
+                        "waiting for previous animation frame");
+                mAnimTransactionPending = false;
+                break;
+            }
+        }
+    }
+
+    size_t count = displays.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const DisplayState& s(displays[i]);
+        transactionFlags |= setDisplayStateLocked(s);
+    }
+
+    count = state.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const ComposerState& s(state[i]);
+        // Here we need to check that the interface we're given is indeed
+        // one of our own. A malicious client could give us a NULL
+        // IInterface, or one of its own or even one of our own but a
+        // different type. All these situations would cause us to crash.
+        //
+        // NOTE: it would be better to use RTTI as we could directly check
+        // that we have a Client*. however, RTTI is disabled in Android.
+        if (s.client != NULL) {
+            sp<IBinder> binder = IInterface::asBinder(s.client);
+            if (binder != NULL) {
+                String16 desc(binder->getInterfaceDescriptor());
+                if (desc == ISurfaceComposerClient::descriptor) {
+                    sp<Client> client( static_cast<Client *>(s.client.get()) );
+                    transactionFlags |= setClientStateLocked(client, s.state);
+                }
+            }
+        }
+    }
+
+    if (transactionFlags) {
+        // this triggers the transaction
+        setTransactionFlags(transactionFlags);
+
+        // if this is a synchronous transaction, wait for it to take effect
+        // before returning.
+        if (flags & eSynchronous) {
+            mTransactionPending = true;
+        }
+        if (flags & eAnimation) {
+            mAnimTransactionPending = true;
+        }
+        while (mTransactionPending) {
+            status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+            if (CC_UNLIKELY(err != NO_ERROR)) {
+                // just in case something goes wrong in SF, return to the
+                // called after a few seconds.
+                ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+                mTransactionPending = false;
+                break;
+            }
+        }
+    }
+}
+
+uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s)
+{
+    ssize_t dpyIdx = mCurrentState.displays.indexOfKey(s.token);
+    if (dpyIdx < 0)
+        return 0;
+
+    uint32_t flags = 0;
+    DisplayDeviceState& disp(mCurrentState.displays.editValueAt(dpyIdx));
+    if (disp.isValid()) {
+        const uint32_t what = s.what;
+        if (what & DisplayState::eSurfaceChanged) {
+            if (IInterface::asBinder(disp.surface) != IInterface::asBinder(s.surface)) {
+                disp.surface = s.surface;
+                flags |= eDisplayTransactionNeeded;
+            }
+        }
+        if (what & DisplayState::eLayerStackChanged) {
+            if (disp.layerStack != s.layerStack) {
+                disp.layerStack = s.layerStack;
+                flags |= eDisplayTransactionNeeded;
+            }
+        }
+        if (what & DisplayState::eDisplayProjectionChanged) {
+            if (disp.orientation != s.orientation) {
+                disp.orientation = s.orientation;
+                flags |= eDisplayTransactionNeeded;
+            }
+            if (disp.frame != s.frame) {
+                disp.frame = s.frame;
+                flags |= eDisplayTransactionNeeded;
+            }
+            if (disp.viewport != s.viewport) {
+                disp.viewport = s.viewport;
+                flags |= eDisplayTransactionNeeded;
+            }
+        }
+        if (what & DisplayState::eDisplaySizeChanged) {
+            if (disp.width != s.width) {
+                disp.width = s.width;
+                flags |= eDisplayTransactionNeeded;
+            }
+            if (disp.height != s.height) {
+                disp.height = s.height;
+                flags |= eDisplayTransactionNeeded;
+            }
+        }
+    }
+    return flags;
+}
+
+uint32_t SurfaceFlinger::setClientStateLocked(
+        const sp<Client>& client,
+        const layer_state_t& s)
+{
+    uint32_t flags = 0;
+    sp<Layer> layer(client->getLayerUser(s.surface));
+    if (layer != 0) {
+        const uint32_t what = s.what;
+        if (what & layer_state_t::ePositionChanged) {
+            if (layer->setPosition(s.x, s.y))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eLayerChanged) {
+            // NOTE: index needs to be calculated before we update the state
+            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+            if (layer->setLayer(s.z) && idx >= 0) {
+                mCurrentState.layersSortedByZ.removeAt(idx);
+                mCurrentState.layersSortedByZ.add(layer);
+                // we need traversal (state changed)
+                // AND transaction (list changed)
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        }
+        if (what & layer_state_t::eSizeChanged) {
+            if (layer->setSize(s.w, s.h)) {
+                flags |= eTraversalNeeded;
+            }
+        }
+        if (what & layer_state_t::eAlphaChanged) {
+            if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eMatrixChanged) {
+            if (layer->setMatrix(s.matrix))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eTransparentRegionChanged) {
+            if (layer->setTransparentRegionHint(s.transparentRegion))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eFlagsChanged) {
+            if (layer->setFlags(s.flags, s.mask))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eCropChanged) {
+            if (layer->setCrop(s.crop))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eFinalCropChanged) {
+            if (layer->setFinalCrop(s.finalCrop))
+                flags |= eTraversalNeeded;
+        }
+        if (what & layer_state_t::eLayerStackChanged) {
+            // NOTE: index needs to be calculated before we update the state
+            ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
+            if (layer->setLayerStack(s.layerStack) && idx >= 0) {
+                mCurrentState.layersSortedByZ.removeAt(idx);
+                mCurrentState.layersSortedByZ.add(layer);
+                // we need traversal (state changed)
+                // AND transaction (list changed)
+                flags |= eTransactionNeeded|eTraversalNeeded;
+            }
+        }
+        if (what & layer_state_t::eDeferTransaction) {
+            layer->deferTransactionUntil(s.handle, s.frameNumber);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
+        if (what & layer_state_t::eOverrideScalingModeChanged) {
+            layer->setOverrideScalingMode(s.overrideScalingMode);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
+    }
+    return flags;
+}
+
+status_t SurfaceFlinger::createLayer(
+        const String8& name,
+        const sp<Client>& client,
+        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
+        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
+{
+    //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string());
+    if (int32_t(w|h) < 0) {
+        ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)",
+                int(w), int(h));
+        return BAD_VALUE;
+    }
+
+    status_t result = NO_ERROR;
+
+    sp<Layer> layer;
+
+    switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
+        case ISurfaceComposerClient::eFXSurfaceNormal:
+            result = createNormalLayer(client,
+                    name, w, h, flags, format,
+                    handle, gbp, &layer);
+            break;
+        case ISurfaceComposerClient::eFXSurfaceDim:
+            result = createDimLayer(client,
+                    name, w, h, flags,
+                    handle, gbp, &layer);
+            break;
+        default:
+            result = BAD_VALUE;
+            break;
+    }
+
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    result = addClientLayer(client, *handle, *gbp, layer);
+    if (result != NO_ERROR) {
+        return result;
+    }
+
+    setTransactionFlags(eTransactionNeeded);
+    return result;
+}
+
+status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
+        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+{
+    // initialize the surfaces
+    switch (format) {
+    case PIXEL_FORMAT_TRANSPARENT:
+    case PIXEL_FORMAT_TRANSLUCENT:
+        format = PIXEL_FORMAT_RGBA_8888;
+        break;
+    case PIXEL_FORMAT_OPAQUE:
+        format = PIXEL_FORMAT_RGBX_8888;
+        break;
+    }
+
+    *outLayer = new Layer(this, client, name, w, h, flags);
+    status_t err = (*outLayer)->setBuffers(w, h, format, flags);
+    if (err == NO_ERROR) {
+        *handle = (*outLayer)->getHandle();
+        *gbp = (*outLayer)->getProducer();
+    }
+
+    ALOGE_IF(err, "createNormalLayer() failed (%s)", strerror(-err));
+    return err;
+}
+
+status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
+        const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+        sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+{
+    *outLayer = new LayerDim(this, client, name, w, h, flags);
+    *handle = (*outLayer)->getHandle();
+    *gbp = (*outLayer)->getProducer();
+    return NO_ERROR;
+}
+
+status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
+{
+    // called by the window manager when it wants to remove a Layer
+    status_t err = NO_ERROR;
+    sp<Layer> l(client->getLayerUser(handle));
+    if (l != NULL) {
+        err = removeLayer(l);
+        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                "error removing layer=%p (%s)", l.get(), strerror(-err));
+    }
+    return err;
+}
+
+status_t SurfaceFlinger::onLayerDestroyed(const wp<Layer>& layer)
+{
+    // called by ~LayerCleaner() when all references to the IBinder (handle)
+    // are gone
+    status_t err = NO_ERROR;
+    sp<Layer> l(layer.promote());
+    if (l != NULL) {
+        err = removeLayer(l);
+        ALOGE_IF(err<0 && err != NAME_NOT_FOUND,
+                "error removing layer=%p (%s)", l.get(), strerror(-err));
+    }
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+
+void SurfaceFlinger::onInitializeDisplays() {
+    // reset screen orientation and use primary layer stack
+    Vector<ComposerState> state;
+    Vector<DisplayState> displays;
+    DisplayState d;
+    d.what = DisplayState::eDisplayProjectionChanged |
+             DisplayState::eLayerStackChanged;
+    d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
+    d.layerStack = 0;
+    d.orientation = DisplayState::eOrientationDefault;
+    d.frame.makeInvalid();
+    d.viewport.makeInvalid();
+    d.width = 0;
+    d.height = 0;
+    displays.add(d);
+    setTransactionState(state, displays, 0);
+    setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
+
+    const nsecs_t period =
+            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+    mAnimFrameTracker.setDisplayRefreshPeriod(period);
+}
+
+void SurfaceFlinger::initializeDisplays() {
+    class MessageScreenInitialized : public MessageBase {
+        SurfaceFlinger* flinger;
+    public:
+        MessageScreenInitialized(SurfaceFlinger* flinger) : flinger(flinger) { }
+        virtual bool handler() {
+            flinger->onInitializeDisplays();
+            return true;
+        }
+    };
+    sp<MessageBase> msg = new MessageScreenInitialized(this);
+    postMessageAsync(msg);  // we may be called from main thread, use async message
+}
+
+void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
+        int mode) {
+    ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+            this);
+    int32_t type = hw->getDisplayType();
+    int currentMode = hw->getPowerMode();
+
+    if (mode == currentMode) {
+        ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
+        return;
+    }
+
+    hw->setPowerMode(mode);
+    if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+        ALOGW("Trying to set power mode for virtual display");
+        return;
+    }
+
+    if (currentMode == HWC_POWER_MODE_OFF) {
+        getHwComposer().setPowerMode(type, mode);
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenAcquired();
+            resyncToHardwareVsync(true);
+        }
+
+        mVisibleRegionsDirty = true;
+        mHasPoweredOff = true;
+        repaintEverything();
+    } else if (mode == HWC_POWER_MODE_OFF) {
+        if (type == DisplayDevice::DISPLAY_PRIMARY) {
+            disableHardwareVsync(true); // also cancels any in-progress resync
+
+            // FIXME: eventthread only knows about the main display right now
+            mEventThread->onScreenReleased();
+        }
+
+        getHwComposer().setPowerMode(type, mode);
+        mVisibleRegionsDirty = true;
+        // from this point on, SF will stop drawing on this display
+    } else {
+        getHwComposer().setPowerMode(type, mode);
+    }
+}
+
+void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
+    class MessageSetPowerMode: public MessageBase {
+        SurfaceFlinger& mFlinger;
+        sp<IBinder> mDisplay;
+        int mMode;
+    public:
+        MessageSetPowerMode(SurfaceFlinger& flinger,
+                const sp<IBinder>& disp, int mode) : mFlinger(flinger),
+                    mDisplay(disp) { mMode = mode; }
+        virtual bool handler() {
+            sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+            if (hw == NULL) {
+                ALOGE("Attempt to set power mode = %d for null display %p",
+                        mMode, mDisplay.get());
+            } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
+                ALOGW("Attempt to set power mode = %d for virtual display",
+                        mMode);
+            } else {
+                mFlinger.setPowerModeInternal(hw, mMode);
+            }
+            return true;
+        }
+    };
+    sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
+    postMessageSync(msg);
+}
+
+// ---------------------------------------------------------------------------
+
+status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
+{
+    String8 result;
+
+    IPCThreadState* ipc = IPCThreadState::self();
+    const int pid = ipc->getCallingPid();
+    const int uid = ipc->getCallingUid();
+    if ((uid != AID_SHELL) &&
+            !PermissionCache::checkPermission(sDump, pid, uid)) {
+        result.appendFormat("Permission Denial: "
+                "can't dump SurfaceFlinger from pid=%d, uid=%d\n", pid, uid);
+    } else {
+        // Try to get the main lock, but give up after one second
+        // (this would indicate SF is stuck, but we want to be able to
+        // print something in dumpsys).
+        status_t err = mStateLock.timedLock(s2ns(1));
+        bool locked = (err == NO_ERROR);
+        if (!locked) {
+            result.appendFormat(
+                    "SurfaceFlinger appears to be unresponsive (%s [%d]), "
+                    "dumping anyways (no locks held)\n", strerror(-err), err);
+        }
+
+        bool dumpAll = true;
+        size_t index = 0;
+        size_t numArgs = args.size();
+        if (numArgs) {
+            if ((index < numArgs) &&
+                    (args[index] == String16("--list"))) {
+                index++;
+                listLayersLocked(args, index, result);
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                    (args[index] == String16("--latency"))) {
+                index++;
+                dumpStatsLocked(args, index, result);
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                    (args[index] == String16("--latency-clear"))) {
+                index++;
+                clearStatsLocked(args, index, result);
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                    (args[index] == String16("--dispsync"))) {
+                index++;
+                mPrimaryDispSync.dump(result);
+                dumpAll = false;
+            }
+
+            if ((index < numArgs) &&
+                    (args[index] == String16("--static-screen"))) {
+                index++;
+                dumpStaticScreenStats(result);
+                dumpAll = false;
+            }
+
+#ifdef ENABLE_FENCE_TRACKING
+            if ((index < numArgs) &&
+                    (args[index] == String16("--fences"))) {
+                index++;
+                mFenceTracker.dump(&result);
+                dumpAll = false;
+            }
+#endif
+        }
+
+        if (dumpAll) {
+            dumpAllLocked(args, index, result);
+        }
+
+        if (locked) {
+            mStateLock.unlock();
+        }
+    }
+    write(fd, result.string(), result.size());
+    return NO_ERROR;
+}
+
+void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */,
+        size_t& /* index */, String8& result) const
+{
+    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    const size_t count = currentLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const sp<Layer>& layer(currentLayers[i]);
+        result.appendFormat("%s\n", layer->getName().string());
+    }
+}
+
+void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index,
+        String8& result) const
+{
+    String8 name;
+    if (index < args.size()) {
+        name = String8(args[index]);
+        index++;
+    }
+
+    const nsecs_t period =
+            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
+    result.appendFormat("%" PRId64 "\n", period);
+
+    if (name.isEmpty()) {
+        mAnimFrameTracker.dumpStats(result);
+    } else {
+        const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+        const size_t count = currentLayers.size();
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<Layer>& layer(currentLayers[i]);
+            if (name == layer->getName()) {
+                layer->dumpFrameStats(result);
+            }
+        }
+    }
+}
+
+void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& index,
+        String8& /* result */)
+{
+    String8 name;
+    if (index < args.size()) {
+        name = String8(args[index]);
+        index++;
+    }
+
+    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    const size_t count = currentLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const sp<Layer>& layer(currentLayers[i]);
+        if (name.isEmpty() || (name == layer->getName())) {
+            layer->clearFrameStats();
+        }
+    }
+
+    mAnimFrameTracker.clearStats();
+}
+
+// This should only be called from the main thread.  Otherwise it would need
+// the lock and should use mCurrentState rather than mDrawingState.
+void SurfaceFlinger::logFrameStats() {
+    const LayerVector& drawingLayers = mDrawingState.layersSortedByZ;
+    const size_t count = drawingLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        const sp<Layer>& layer(drawingLayers[i]);
+        layer->logFrameStats();
+    }
+
+    mAnimFrameTracker.logAndResetStats(String8("<win-anim>"));
+}
+
+/*static*/ void SurfaceFlinger::appendSfConfigString(String8& result)
+{
+    static const char* config =
+            " [sf"
+#ifdef HAS_CONTEXT_PRIORITY
+            " HAS_CONTEXT_PRIORITY"
+#endif
+#ifdef NEVER_DEFAULT_TO_ASYNC_MODE
+            " NEVER_DEFAULT_TO_ASYNC_MODE"
+#endif
+#ifdef TARGET_DISABLE_TRIPLE_BUFFERING
+            " TARGET_DISABLE_TRIPLE_BUFFERING"
+#endif
+            "]";
+    result.append(config);
+}
+
+void SurfaceFlinger::dumpStaticScreenStats(String8& result) const
+{
+    result.appendFormat("Static screen stats:\n");
+    for (size_t b = 0; b < NUM_BUCKETS - 1; ++b) {
+        float bucketTimeSec = mFrameBuckets[b] / 1e9;
+        float percent = 100.0f *
+                static_cast<float>(mFrameBuckets[b]) / mTotalTime;
+        result.appendFormat("  < %zd frames: %.3f s (%.1f%%)\n",
+                b + 1, bucketTimeSec, percent);
+    }
+    float bucketTimeSec = mFrameBuckets[NUM_BUCKETS - 1] / 1e9;
+    float percent = 100.0f *
+            static_cast<float>(mFrameBuckets[NUM_BUCKETS - 1]) / mTotalTime;
+    result.appendFormat("  %zd+ frames: %.3f s (%.1f%%)\n",
+            NUM_BUCKETS - 1, bucketTimeSec, percent);
+}
+
+void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
+        String8& result) const
+{
+    bool colorize = false;
+    if (index < args.size()
+            && (args[index] == String16("--color"))) {
+        colorize = true;
+        index++;
+    }
+
+    Colorizer colorizer(colorize);
+
+    // figure out if we're stuck somewhere
+    const nsecs_t now = systemTime();
+    const nsecs_t inSwapBuffers(mDebugInSwapBuffers);
+    const nsecs_t inTransaction(mDebugInTransaction);
+    nsecs_t inSwapBuffersDuration = (inSwapBuffers) ? now-inSwapBuffers : 0;
+    nsecs_t inTransactionDuration = (inTransaction) ? now-inTransaction : 0;
+
+    /*
+     * Dump library configuration.
+     */
+
+    colorizer.bold(result);
+    result.append("Build configuration:");
+    colorizer.reset(result);
+    appendSfConfigString(result);
+    appendUiConfigString(result);
+    appendGuiConfigString(result);
+    result.append("\n");
+
+    colorizer.bold(result);
+    result.append("Sync configuration: ");
+    colorizer.reset(result);
+    result.append(SyncFeatures::getInstance().toString());
+    result.append("\n");
+
+    colorizer.bold(result);
+    result.append("DispSync configuration: ");
+    colorizer.reset(result);
+    result.appendFormat("app phase %" PRId64 " ns, sf phase %" PRId64 " ns, "
+            "present offset %d ns (refresh %" PRId64 " ns)",
+        vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, PRESENT_TIME_OFFSET_FROM_VSYNC_NS,
+        mHwc->getRefreshPeriod(HWC_DISPLAY_PRIMARY));
+    result.append("\n");
+
+    // Dump static screen stats
+    result.append("\n");
+    dumpStaticScreenStats(result);
+    result.append("\n");
+
+    /*
+     * Dump the visible layer list
+     */
+    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    const size_t count = currentLayers.size();
+    colorizer.bold(result);
+    result.appendFormat("Visible layers (count = %zu)\n", count);
+    colorizer.reset(result);
+    for (size_t i=0 ; i<count ; i++) {
+        const sp<Layer>& layer(currentLayers[i]);
+        layer->dump(result, colorizer);
+    }
+
+    /*
+     * Dump Display state
+     */
+
+    colorizer.bold(result);
+    result.appendFormat("Displays (%zu entries)\n", mDisplays.size());
+    colorizer.reset(result);
+    for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
+        const sp<const DisplayDevice>& hw(mDisplays[dpy]);
+        hw->dump(result);
+    }
+
+    /*
+     * Dump SurfaceFlinger global state
+     */
+
+    colorizer.bold(result);
+    result.append("SurfaceFlinger global state:\n");
+    colorizer.reset(result);
+
+    HWComposer& hwc(getHwComposer());
+    sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+
+    colorizer.bold(result);
+    result.appendFormat("EGL implementation : %s\n",
+            eglQueryStringImplementationANDROID(mEGLDisplay, EGL_VERSION));
+    colorizer.reset(result);
+    result.appendFormat("%s\n",
+            eglQueryStringImplementationANDROID(mEGLDisplay, EGL_EXTENSIONS));
+
+    mRenderEngine->dump(result);
+
+    hw->undefinedRegion.dump(result, "undefinedRegion");
+    result.appendFormat("  orientation=%d, isDisplayOn=%d\n",
+            hw->getOrientation(), hw->isDisplayOn());
+    result.appendFormat(
+            "  last eglSwapBuffers() time: %f us\n"
+            "  last transaction time     : %f us\n"
+            "  transaction-flags         : %08x\n"
+            "  refresh-rate              : %f fps\n"
+            "  x-dpi                     : %f\n"
+            "  y-dpi                     : %f\n"
+            "  gpu_to_cpu_unsupported    : %d\n"
+            ,
+            mLastSwapBufferTime/1000.0,
+            mLastTransactionTime/1000.0,
+            mTransactionFlags,
+            1e9 / hwc.getRefreshPeriod(HWC_DISPLAY_PRIMARY),
+            hwc.getDpiX(HWC_DISPLAY_PRIMARY),
+            hwc.getDpiY(HWC_DISPLAY_PRIMARY),
+            !mGpuToCpuSupported);
+
+    result.appendFormat("  eglSwapBuffers time: %f us\n",
+            inSwapBuffersDuration/1000.0);
+
+    result.appendFormat("  transaction time: %f us\n",
+            inTransactionDuration/1000.0);
+
+    /*
+     * VSYNC state
+     */
+    mEventThread->dump(result);
+
+    /*
+     * Dump HWComposer state
+     */
+    colorizer.bold(result);
+    result.append("h/w composer state:\n");
+    colorizer.reset(result);
+    result.appendFormat("  h/w composer %s and %s\n",
+            hwc.initCheck()==NO_ERROR ? "present" : "not present",
+                    (mDebugDisableHWC || mDebugRegion || mDaltonize
+                            || mHasColorMatrix) ? "disabled" : "enabled");
+    hwc.dump(result);
+
+    /*
+     * Dump gralloc state
+     */
+    const GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+    alloc.dump(result);
+}
+
+const Vector< sp<Layer> >&
+SurfaceFlinger::getLayerSortedByZForHwcDisplay(int id) {
+    // Note: mStateLock is held here
+    wp<IBinder> dpy;
+    for (size_t i=0 ; i<mDisplays.size() ; i++) {
+        if (mDisplays.valueAt(i)->getHwcDisplayId() == id) {
+            dpy = mDisplays.keyAt(i);
+            break;
+        }
+    }
+    if (dpy == NULL) {
+        ALOGE("getLayerSortedByZForHwcDisplay: invalid hwc display id %d", id);
+        // Just use the primary display so we have something to return
+        dpy = getBuiltInDisplay(DisplayDevice::DISPLAY_PRIMARY);
+    }
+    return getDisplayDevice(dpy)->getVisibleLayersSortedByZ();
+}
+
+bool SurfaceFlinger::startDdmConnection()
+{
+    void* libddmconnection_dso =
+            dlopen("libsurfaceflinger_ddmconnection.so", RTLD_NOW);
+    if (!libddmconnection_dso) {
+        return false;
+    }
+    void (*DdmConnection_start)(const char* name);
+    DdmConnection_start =
+            (decltype(DdmConnection_start))dlsym(libddmconnection_dso, "DdmConnection_start");
+    if (!DdmConnection_start) {
+        dlclose(libddmconnection_dso);
+        return false;
+    }
+    (*DdmConnection_start)(getServiceName());
+    return true;
+}
+
+status_t SurfaceFlinger::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    switch (code) {
+        case CREATE_CONNECTION:
+        case CREATE_DISPLAY:
+        case SET_TRANSACTION_STATE:
+        case BOOT_FINISHED:
+        case CLEAR_ANIMATION_FRAME_STATS:
+        case GET_ANIMATION_FRAME_STATS:
+        case SET_POWER_MODE:
+        case GET_HDR_CAPABILITIES:
+        {
+            // codes that require permission check
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            if ((uid != AID_GRAPHICS && uid != AID_SYSTEM) &&
+                    !PermissionCache::checkPermission(sAccessSurfaceFlinger, pid, uid)) {
+                ALOGE("Permission Denial: "
+                        "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
+            }
+            break;
+        }
+        case CAPTURE_SCREEN:
+        {
+            // codes that require permission check
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            if ((uid != AID_GRAPHICS) &&
+                    !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+                ALOGE("Permission Denial: "
+                        "can't read framebuffer pid=%d, uid=%d", pid, uid);
+                return PERMISSION_DENIED;
+            }
+            break;
+        }
+    }
+
+    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
+    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
+        CHECK_INTERFACE(ISurfaceComposer, data, reply);
+        if (CC_UNLIKELY(!PermissionCache::checkCallingPermission(sHardwareTest))) {
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
+            ALOGE("Permission Denial: "
+                    "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
+            return PERMISSION_DENIED;
+        }
+        int n;
+        switch (code) {
+            case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
+            case 1001: // SHOW_FPS, NOT SUPPORTED ANYMORE
+                return NO_ERROR;
+            case 1002:  // SHOW_UPDATES
+                n = data.readInt32();
+                mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            case 1004:{ // repaint everything
+                repaintEverything();
+                return NO_ERROR;
+            }
+            case 1005:{ // force transaction
+                setTransactionFlags(
+                        eTransactionNeeded|
+                        eDisplayTransactionNeeded|
+                        eTraversalNeeded);
+                return NO_ERROR;
+            }
+            case 1006:{ // send empty update
+                signalRefresh();
+                return NO_ERROR;
+            }
+            case 1008:  // toggle use of hw composer
+                n = data.readInt32();
+                mDebugDisableHWC = n ? 1 : 0;
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            case 1009:  // toggle use of transform hint
+                n = data.readInt32();
+                mDebugDisableTransformHint = n ? 1 : 0;
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            case 1010:  // interrogate.
+                reply->writeInt32(0);
+                reply->writeInt32(0);
+                reply->writeInt32(mDebugRegion);
+                reply->writeInt32(0);
+                reply->writeInt32(mDebugDisableHWC);
+                return NO_ERROR;
+            case 1013: {
+                Mutex::Autolock _l(mStateLock);
+                sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+                reply->writeInt32(hw->getPageFlipCount());
+                return NO_ERROR;
+            }
+            case 1014: {
+                // daltonize
+                n = data.readInt32();
+                switch (n % 10) {
+                    case 1: mDaltonizer.setType(Daltonizer::protanomaly);   break;
+                    case 2: mDaltonizer.setType(Daltonizer::deuteranomaly); break;
+                    case 3: mDaltonizer.setType(Daltonizer::tritanomaly);   break;
+                }
+                if (n >= 10) {
+                    mDaltonizer.setMode(Daltonizer::correction);
+                } else {
+                    mDaltonizer.setMode(Daltonizer::simulation);
+                }
+                mDaltonize = n > 0;
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
+            case 1015: {
+                // apply a color matrix
+                n = data.readInt32();
+                mHasColorMatrix = n ? 1 : 0;
+                if (n) {
+                    // color matrix is sent as mat3 matrix followed by vec3
+                    // offset, then packed into a mat4 where the last row is
+                    // the offset and extra values are 0
+                    for (size_t i = 0 ; i < 4; i++) {
+                      for (size_t j = 0; j < 4; j++) {
+                          mColorMatrix[i][j] = data.readFloat();
+                      }
+                    }
+                } else {
+                    mColorMatrix = mat4();
+                }
+                invalidateHwcGeometry();
+                repaintEverything();
+                return NO_ERROR;
+            }
+            // This is an experimental interface
+            // Needs to be shifted to proper binder interface when we productize
+            case 1016: {
+                n = data.readInt32();
+                mPrimaryDispSync.setRefreshSkipCount(n);
+                return NO_ERROR;
+            }
+            case 1017: {
+                n = data.readInt32();
+                mForceFullDamage = static_cast<bool>(n);
+                return NO_ERROR;
+            }
+            case 1018: { // Modify Choreographer's phase offset
+                n = data.readInt32();
+                mEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+                return NO_ERROR;
+            }
+            case 1019: { // Modify SurfaceFlinger's phase offset
+                n = data.readInt32();
+                mSFEventThread->setPhaseOffset(static_cast<nsecs_t>(n));
+                return NO_ERROR;
+            }
+        }
+    }
+    return err;
+}
+
+void SurfaceFlinger::repaintEverything() {
+    android_atomic_or(1, &mRepaintEverything);
+    signalTransaction();
+}
+
+// ---------------------------------------------------------------------------
+// Capture screen into an IGraphiBufferProducer
+// ---------------------------------------------------------------------------
+
+/* The code below is here to handle b/8734824
+ *
+ * We create a IGraphicBufferProducer wrapper that forwards all calls
+ * from the surfaceflinger thread to the calling binder thread, where they
+ * are executed. This allows the calling thread in the calling process to be
+ * reused and not depend on having "enough" binder threads to handle the
+ * requests.
+ */
+class GraphicProducerWrapper : public BBinder, public MessageHandler {
+    /* Parts of GraphicProducerWrapper are run on two different threads,
+     * communicating by sending messages via Looper but also by shared member
+     * data. Coherence maintenance is subtle and in places implicit (ugh).
+     *
+     * Don't rely on Looper's sendMessage/handleMessage providing
+     * release/acquire semantics for any data not actually in the Message.
+     * Data going from surfaceflinger to binder threads needs to be
+     * synchronized explicitly.
+     *
+     * Barrier open/wait do provide release/acquire semantics. This provides
+     * implicit synchronization for data coming back from binder to
+     * surfaceflinger threads.
+     */
+
+    sp<IGraphicBufferProducer> impl;
+    sp<Looper> looper;
+    status_t result;
+    bool exitPending;
+    bool exitRequested;
+    Barrier barrier;
+    uint32_t code;
+    Parcel const* data;
+    Parcel* reply;
+
+    enum {
+        MSG_API_CALL,
+        MSG_EXIT
+    };
+
+    /*
+     * Called on surfaceflinger thread. This is called by our "fake"
+     * BpGraphicBufferProducer. We package the data and reply Parcel and
+     * forward them to the binder thread.
+     */
+    virtual status_t transact(uint32_t code,
+            const Parcel& data, Parcel* reply, uint32_t /* flags */) {
+        this->code = code;
+        this->data = &data;
+        this->reply = reply;
+        if (exitPending) {
+            // if we've exited, we run the message synchronously right here.
+            // note (JH): as far as I can tell from looking at the code, this
+            // never actually happens. if it does, i'm not sure if it happens
+            // on the surfaceflinger or binder thread.
+            handleMessage(Message(MSG_API_CALL));
+        } else {
+            barrier.close();
+            // Prevent stores to this->{code, data, reply} from being
+            // reordered later than the construction of Message.
+            atomic_thread_fence(memory_order_release);
+            looper->sendMessage(this, Message(MSG_API_CALL));
+            barrier.wait();
+        }
+        return result;
+    }
+
+    /*
+     * here we run on the binder thread. All we've got to do is
+     * call the real BpGraphicBufferProducer.
+     */
+    virtual void handleMessage(const Message& message) {
+        int what = message.what;
+        // Prevent reads below from happening before the read from Message
+        atomic_thread_fence(memory_order_acquire);
+        if (what == MSG_API_CALL) {
+            result = IInterface::asBinder(impl)->transact(code, data[0], reply);
+            barrier.open();
+        } else if (what == MSG_EXIT) {
+            exitRequested = true;
+        }
+    }
+
+public:
+    GraphicProducerWrapper(const sp<IGraphicBufferProducer>& impl)
+    :   impl(impl),
+        looper(new Looper(true)),
+        result(NO_ERROR),
+        exitPending(false),
+        exitRequested(false),
+        code(0),
+        data(NULL),
+        reply(NULL)
+    {}
+
+    // Binder thread
+    status_t waitForResponse() {
+        do {
+            looper->pollOnce(-1);
+        } while (!exitRequested);
+        return result;
+    }
+
+    // Client thread
+    void exit(status_t result) {
+        this->result = result;
+        exitPending = true;
+        // Ensure this->result is visible to the binder thread before it
+        // handles the message.
+        atomic_thread_fence(memory_order_release);
+        looper->sendMessage(this, Message(MSG_EXIT));
+    }
+};
+
+
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
+        const sp<IGraphicBufferProducer>& producer,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool useIdentityTransform, ISurfaceComposer::Rotation rotation) {
+
+    if (CC_UNLIKELY(display == 0))
+        return BAD_VALUE;
+
+    if (CC_UNLIKELY(producer == 0))
+        return BAD_VALUE;
+
+    // if we have secure windows on this display, never allow the screen capture
+    // unless the producer interface is local (i.e.: we can take a screenshot for
+    // ourselves).
+    bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
+
+    // Convert to surfaceflinger's internal rotation type.
+    Transform::orientation_flags rotationFlags;
+    switch (rotation) {
+        case ISurfaceComposer::eRotateNone:
+            rotationFlags = Transform::ROT_0;
+            break;
+        case ISurfaceComposer::eRotate90:
+            rotationFlags = Transform::ROT_90;
+            break;
+        case ISurfaceComposer::eRotate180:
+            rotationFlags = Transform::ROT_180;
+            break;
+        case ISurfaceComposer::eRotate270:
+            rotationFlags = Transform::ROT_270;
+            break;
+        default:
+            rotationFlags = Transform::ROT_0;
+            ALOGE("Invalid rotation passed to captureScreen(): %d\n", rotation);
+            break;
+    }
+
+    class MessageCaptureScreen : public MessageBase {
+        SurfaceFlinger* flinger;
+        sp<IBinder> display;
+        sp<IGraphicBufferProducer> producer;
+        Rect sourceCrop;
+        uint32_t reqWidth, reqHeight;
+        uint32_t minLayerZ,maxLayerZ;
+        bool useIdentityTransform;
+        Transform::orientation_flags rotation;
+        status_t result;
+        bool isLocalScreenshot;
+    public:
+        MessageCaptureScreen(SurfaceFlinger* flinger,
+                const sp<IBinder>& display,
+                const sp<IGraphicBufferProducer>& producer,
+                Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+                uint32_t minLayerZ, uint32_t maxLayerZ,
+                bool useIdentityTransform,
+                Transform::orientation_flags rotation,
+                bool isLocalScreenshot)
+            : flinger(flinger), display(display), producer(producer),
+              sourceCrop(sourceCrop), reqWidth(reqWidth), reqHeight(reqHeight),
+              minLayerZ(minLayerZ), maxLayerZ(maxLayerZ),
+              useIdentityTransform(useIdentityTransform),
+              rotation(rotation), result(PERMISSION_DENIED),
+              isLocalScreenshot(isLocalScreenshot)
+        {
+        }
+        status_t getResult() const {
+            return result;
+        }
+        virtual bool handler() {
+            Mutex::Autolock _l(flinger->mStateLock);
+            sp<const DisplayDevice> hw(flinger->getDisplayDevice(display));
+            result = flinger->captureScreenImplLocked(hw, producer,
+                    sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    useIdentityTransform, rotation, isLocalScreenshot);
+            static_cast<GraphicProducerWrapper*>(IInterface::asBinder(producer).get())->exit(result);
+            return true;
+        }
+    };
+
+    // make sure to process transactions before screenshots -- a transaction
+    // might already be pending but scheduled for VSYNC; this guarantees we
+    // will handle it before the screenshot. When VSYNC finally arrives
+    // the scheduled transaction will be a no-op. If no transactions are
+    // scheduled at this time, this will end-up being a no-op as well.
+    mEventQueue.invalidateTransactionNow();
+
+    // this creates a "fake" BBinder which will serve as a "fake" remote
+    // binder to receive the marshaled calls and forward them to the
+    // real remote (a BpGraphicBufferProducer)
+    sp<GraphicProducerWrapper> wrapper = new GraphicProducerWrapper(producer);
+
+    // the asInterface() call below creates our "fake" BpGraphicBufferProducer
+    // which does the marshaling work forwards to our "fake remote" above.
+    sp<MessageBase> msg = new MessageCaptureScreen(this,
+            display, IGraphicBufferProducer::asInterface( wrapper ),
+            sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+            useIdentityTransform, rotationFlags, isLocalScreenshot);
+
+    status_t res = postMessageAsync(msg);
+    if (res == NO_ERROR) {
+        res = wrapper->waitForResponse();
+    }
+    return res;
+}
+
+
+void SurfaceFlinger::renderScreenImplLocked(
+        const sp<const DisplayDevice>& hw,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation)
+{
+    ATRACE_CALL();
+    RenderEngine& engine(getRenderEngine());
+
+    // get screen geometry
+    const int32_t hw_w = hw->getWidth();
+    const int32_t hw_h = hw->getHeight();
+    const bool filtering = static_cast<int32_t>(reqWidth) != hw_w ||
+                           static_cast<int32_t>(reqHeight) != hw_h;
+
+    // if a default or invalid sourceCrop is passed in, set reasonable values
+    if (sourceCrop.width() == 0 || sourceCrop.height() == 0 ||
+            !sourceCrop.isValid()) {
+        sourceCrop.setLeftTop(Point(0, 0));
+        sourceCrop.setRightBottom(Point(hw_w, hw_h));
+    }
+
+    // ensure that sourceCrop is inside screen
+    if (sourceCrop.left < 0) {
+        ALOGE("Invalid crop rect: l = %d (< 0)", sourceCrop.left);
+    }
+    if (sourceCrop.right > hw_w) {
+        ALOGE("Invalid crop rect: r = %d (> %d)", sourceCrop.right, hw_w);
+    }
+    if (sourceCrop.top < 0) {
+        ALOGE("Invalid crop rect: t = %d (< 0)", sourceCrop.top);
+    }
+    if (sourceCrop.bottom > hw_h) {
+        ALOGE("Invalid crop rect: b = %d (> %d)", sourceCrop.bottom, hw_h);
+    }
+
+    // make sure to clear all GL error flags
+    engine.checkErrors();
+
+    // set-up our viewport
+    engine.setViewportAndProjection(
+        reqWidth, reqHeight, sourceCrop, hw_h, yswap, rotation);
+    engine.disableTexturing();
+
+    // redraw the screen entirely...
+    engine.clearWithColor(0, 0, 0, 1);
+
+    const LayerVector& layers( mDrawingState.layersSortedByZ );
+    const size_t count = layers.size();
+    for (size_t i=0 ; i<count ; ++i) {
+        const sp<Layer>& layer(layers[i]);
+        const Layer::State& state(layer->getDrawingState());
+        if (state.layerStack == hw->getLayerStack()) {
+            if (state.z >= minLayerZ && state.z <= maxLayerZ) {
+                if (layer->isVisible()) {
+                    if (filtering) layer->setFiltering(true);
+                    layer->draw(hw, useIdentityTransform);
+                    if (filtering) layer->setFiltering(false);
+                }
+            }
+        }
+    }
+
+    // compositionComplete is needed for older driver
+    hw->compositionComplete();
+    hw->setViewportAndProjection();
+}
+
+
+status_t SurfaceFlinger::captureScreenImplLocked(
+        const sp<const DisplayDevice>& hw,
+        const sp<IGraphicBufferProducer>& producer,
+        Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+        uint32_t minLayerZ, uint32_t maxLayerZ,
+        bool useIdentityTransform, Transform::orientation_flags rotation,
+        bool isLocalScreenshot)
+{
+    ATRACE_CALL();
+
+    // get screen geometry
+    uint32_t hw_w = hw->getWidth();
+    uint32_t hw_h = hw->getHeight();
+
+    if (rotation & Transform::ROT_90) {
+        std::swap(hw_w, hw_h);
+    }
+
+    if ((reqWidth > hw_w) || (reqHeight > hw_h)) {
+        ALOGE("size mismatch (%d, %d) > (%d, %d)",
+                reqWidth, reqHeight, hw_w, hw_h);
+        return BAD_VALUE;
+    }
+
+    reqWidth  = (!reqWidth)  ? hw_w : reqWidth;
+    reqHeight = (!reqHeight) ? hw_h : reqHeight;
+
+    bool secureLayerIsVisible = false;
+    const LayerVector& layers(mDrawingState.layersSortedByZ);
+    const size_t count = layers.size();
+    for (size_t i = 0 ; i < count ; ++i) {
+        const sp<Layer>& layer(layers[i]);
+        const Layer::State& state(layer->getDrawingState());
+        if (state.layerStack == hw->getLayerStack() && state.z >= minLayerZ &&
+                state.z <= maxLayerZ && layer->isVisible() &&
+                layer->isSecure()) {
+            secureLayerIsVisible = true;
+        }
+    }
+
+    if (!isLocalScreenshot && secureLayerIsVisible) {
+        ALOGW("FB is protected: PERMISSION_DENIED");
+        return PERMISSION_DENIED;
+    }
+
+    // create a surface (because we're a producer, and we need to
+    // dequeue/queue a buffer)
+    sp<Surface> sur = new Surface(producer, false);
+    ANativeWindow* window = sur.get();
+
+    status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+    if (result == NO_ERROR) {
+        uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+                        GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+
+        int err = 0;
+        err = native_window_set_buffers_dimensions(window, reqWidth, reqHeight);
+        err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+        err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+        err |= native_window_set_usage(window, usage);
+
+        if (err == NO_ERROR) {
+            ANativeWindowBuffer* buffer;
+            /* TODO: Once we have the sync framework everywhere this can use
+             * server-side waits on the fence that dequeueBuffer returns.
+             */
+            result = native_window_dequeue_buffer_and_wait(window,  &buffer);
+            if (result == NO_ERROR) {
+                int syncFd = -1;
+                // create an EGLImage from the buffer so we can later
+                // turn it into a texture
+                EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
+                        EGL_NATIVE_BUFFER_ANDROID, buffer, NULL);
+                if (image != EGL_NO_IMAGE_KHR) {
+                    // this binds the given EGLImage as a framebuffer for the
+                    // duration of this scope.
+                    RenderEngine::BindImageAsFramebuffer imageBond(getRenderEngine(), image);
+                    if (imageBond.getStatus() == NO_ERROR) {
+                        // this will in fact render into our dequeued buffer
+                        // via an FBO, which means we didn't have to create
+                        // an EGLSurface and therefore we're not
+                        // dependent on the context's EGLConfig.
+                        renderScreenImplLocked(
+                            hw, sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ, true,
+                            useIdentityTransform, rotation);
+
+                        // Attempt to create a sync khr object that can produce a sync point. If that
+                        // isn't available, create a non-dupable sync object in the fallback path and
+                        // wait on it directly.
+                        EGLSyncKHR sync;
+                        if (!DEBUG_SCREENSHOTS) {
+                           sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, NULL);
+                           // native fence fd will not be populated until flush() is done.
+                           getRenderEngine().flush();
+                        } else {
+                            sync = EGL_NO_SYNC_KHR;
+                        }
+                        if (sync != EGL_NO_SYNC_KHR) {
+                            // get the sync fd
+                            syncFd = eglDupNativeFenceFDANDROID(mEGLDisplay, sync);
+                            if (syncFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
+                                ALOGW("captureScreen: failed to dup sync khr object");
+                                syncFd = -1;
+                            }
+                            eglDestroySyncKHR(mEGLDisplay, sync);
+                        } else {
+                            // fallback path
+                            sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, NULL);
+                            if (sync != EGL_NO_SYNC_KHR) {
+                                EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync,
+                                    EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, 2000000000 /*2 sec*/);
+                                EGLint eglErr = eglGetError();
+                                if (result == EGL_TIMEOUT_EXPIRED_KHR) {
+                                    ALOGW("captureScreen: fence wait timed out");
+                                } else {
+                                    ALOGW_IF(eglErr != EGL_SUCCESS,
+                                            "captureScreen: error waiting on EGL fence: %#x", eglErr);
+                                }
+                                eglDestroySyncKHR(mEGLDisplay, sync);
+                            } else {
+                                ALOGW("captureScreen: error creating EGL fence: %#x", eglGetError());
+                            }
+                        }
+                        if (DEBUG_SCREENSHOTS) {
+                            uint32_t* pixels = new uint32_t[reqWidth*reqHeight];
+                            getRenderEngine().readPixels(0, 0, reqWidth, reqHeight, pixels);
+                            checkScreenshot(reqWidth, reqHeight, reqWidth, pixels,
+                                    hw, minLayerZ, maxLayerZ);
+                            delete [] pixels;
+                        }
+
+                    } else {
+                        ALOGE("got GL_FRAMEBUFFER_COMPLETE_OES error while taking screenshot");
+                        result = INVALID_OPERATION;
+                        window->cancelBuffer(window, buffer, syncFd);
+                        buffer = NULL;
+                    }
+                    // destroy our image
+                    eglDestroyImageKHR(mEGLDisplay, image);
+                } else {
+                    result = BAD_VALUE;
+                }
+                if (buffer) {
+                    // queueBuffer takes ownership of syncFd
+                    result = window->queueBuffer(window, buffer, syncFd);
+                }
+            }
+        } else {
+            result = BAD_VALUE;
+        }
+        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
+    }
+
+    return result;
+}
+
+void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
+        const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ) {
+    if (DEBUG_SCREENSHOTS) {
+        for (size_t y=0 ; y<h ; y++) {
+            uint32_t const * p = (uint32_t const *)vaddr + y*s;
+            for (size_t x=0 ; x<w ; x++) {
+                if (p[x] != 0xFF000000) return;
+            }
+        }
+        ALOGE("*** we just took a black screenshot ***\n"
+                "requested minz=%d, maxz=%d, layerStack=%d",
+                minLayerZ, maxLayerZ, hw->getLayerStack());
+        const LayerVector& layers( mDrawingState.layersSortedByZ );
+        const size_t count = layers.size();
+        for (size_t i=0 ; i<count ; ++i) {
+            const sp<Layer>& layer(layers[i]);
+            const Layer::State& state(layer->getDrawingState());
+            const bool visible = (state.layerStack == hw->getLayerStack())
+                                && (state.z >= minLayerZ && state.z <= maxLayerZ)
+                                && (layer->isVisible());
+            ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x",
+                    visible ? '+' : '-',
+                            i, layer->getName().string(), state.layerStack, state.z,
+                            layer->isVisible(), state.flags, state.alpha);
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+SurfaceFlinger::LayerVector::LayerVector() {
+}
+
+SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs)
+    : SortedVector<sp<Layer> >(rhs) {
+}
+
+int SurfaceFlinger::LayerVector::do_compare(const void* lhs,
+    const void* rhs) const
+{
+    // sort layers per layer-stack, then by z-order and finally by sequence
+    const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs));
+    const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs));
+
+    uint32_t ls = l->getCurrentState().layerStack;
+    uint32_t rs = r->getCurrentState().layerStack;
+    if (ls != rs)
+        return ls - rs;
+
+    uint32_t lz = l->getCurrentState().z;
+    uint32_t rz = r->getCurrentState().z;
+    if (lz != rz)
+        return lz - rz;
+
+    return l->sequence - r->sequence;
+}
+
+// ---------------------------------------------------------------------------
+
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState()
+    : type(DisplayDevice::DISPLAY_ID_INVALID),
+      layerStack(DisplayDevice::NO_LAYER_STACK),
+      orientation(0),
+      width(0),
+      height(0),
+      isSecure(false) {
+}
+
+SurfaceFlinger::DisplayDeviceState::DisplayDeviceState(
+    DisplayDevice::DisplayType type, bool isSecure)
+    : type(type),
+      layerStack(DisplayDevice::NO_LAYER_STACK),
+      orientation(0),
+      width(0),
+      height(0),
+      isSecure(isSecure) {
+    viewport.makeInvalid();
+    frame.makeInvalid();
+}
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+
+#if defined(__gl_h_)
+#error "don't include gl/gl.h in this file"
+#endif
+
+#if defined(__gl2_h_)
+#error "don't include gl2/gl2.h in this file"
+#endif
diff --git a/services/surfaceflinger/Transform.h b/services/surfaceflinger/Transform.h
index c2f0010..9efeb9e 100644
--- a/services/surfaceflinger/Transform.h
+++ b/services/surfaceflinger/Transform.h
@@ -81,6 +81,9 @@
             Region  transform(const Region& reg) const;
             Rect    transform(const Rect& bounds) const;
             Transform operator * (const Transform& rhs) const;
+            // assumes the last row is < 0 , 0 , 1 >
+            vec2 transform(const vec2& v) const;
+            vec3 transform(const vec3& v) const;
 
             Transform inverse() const;
 
@@ -96,9 +99,6 @@
 
     enum { UNKNOWN_TYPE = 0x80000000 };
 
-    // assumes the last row is < 0 , 0 , 1 >
-    vec2 transform(const vec2& v) const;
-    vec3 transform(const vec3& v) const;
     uint32_t type() const;
     static bool absIsOne(float f);
     static bool isZero(float f);
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 6fa8b53..97a1e8b 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -21,11 +21,13 @@
 #include <binder/IPCThreadState.h>
 #include <binder/ProcessState.h>
 #include <binder/IServiceManager.h>
+#include "GpuService.h"
 #include "SurfaceFlinger.h"
 
 using namespace android;
 
 int main(int, char**) {
+    signal(SIGPIPE, SIG_IGN);
     // When SF is launched in its own process, limit the number of
     // binder threads to 4.
     ProcessState::self()->setThreadPoolMaxThreadCount(4);
@@ -55,7 +57,11 @@
     sp<IServiceManager> sm(defaultServiceManager());
     sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
 
-    // run in this thread
+    // publish GpuService
+    sp<GpuService> gpuservice = new GpuService();
+    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);
+
+    // run surface flinger in this thread
     flinger->run();
 
     return 0;
diff --git a/services/surfaceflinger/surfaceflinger.rc b/services/surfaceflinger/surfaceflinger.rc
new file mode 100644
index 0000000..2b4ea2a
--- /dev/null
+++ b/services/surfaceflinger/surfaceflinger.rc
@@ -0,0 +1,6 @@
+service surfaceflinger /system/bin/surfaceflinger
+    class core
+    user system
+    group graphics drmrpc readproc
+    onrestart restart zygote
+    writepid /sys/fs/cgroup/stune/foreground/tasks
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index dcde512..320fddb 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -24,10 +24,13 @@
 #include <gui/Surface.h>
 #include <gui/SurfaceComposerClient.h>
 #include <private/gui/ComposerService.h>
+#include <private/gui/LayerState.h>
 
 #include <utils/String8.h>
 #include <ui/DisplayInfo.h>
 
+#include <math.h>
+
 namespace android {
 
 // Fill an RGBA_8888 formatted surface with a single color.
@@ -38,8 +41,8 @@
     ASSERT_TRUE(s != NULL);
     ASSERT_EQ(NO_ERROR, s->lock(&outBuffer, NULL));
     uint8_t* img = reinterpret_cast<uint8_t*>(outBuffer.bits);
-    for (uint32_t y = 0; y < outBuffer.height; y++) {
-        for (uint32_t x = 0; x < outBuffer.width; x++) {
+    for (int y = 0; y < outBuffer.height; y++) {
+        for (int x = 0; x < outBuffer.width; x++) {
             uint8_t* pixel = img + (4 * (y*outBuffer.stride + x));
             pixel[0] = r;
             pixel[1] = g;
@@ -76,7 +79,7 @@
             String8 err(String8::format("pixel @ (%3d, %3d): "
                     "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
                     x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
-            EXPECT_EQ(String8(), err);
+            EXPECT_EQ(String8(), err) << err.string();
         }
     }
 
@@ -134,6 +137,8 @@
 
         SurfaceComposerClient::openGlobalTransaction();
 
+        mComposerClient->setDisplayLayerStack(display, 0);
+
         ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-2));
         ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show());
 
@@ -249,4 +254,266 @@
     }
 }
 
+TEST_F(LayerUpdateTest, LayerCropWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before crop");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    Rect cropRect(16, 16, 32, 32);
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setCrop(cropRect));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should crop the foreground surface.
+        SCOPED_TRACE("after crop");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel( 95,  80, 195,  63,  63);
+        sc->checkPixel( 80,  95, 195,  63,  63);
+        sc->checkPixel( 96,  96,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerFinalCropWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before crop");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+    SurfaceComposerClient::openGlobalTransaction();
+    Rect cropRect(16, 16, 32, 32);
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFinalCrop(cropRect));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should crop the foreground surface.
+        SCOPED_TRACE("after crop");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel( 95,  80,  63,  63, 195);
+        sc->checkPixel( 80,  95,  63,  63, 195);
+        sc->checkPixel( 96,  96,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetLayerWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setLayer");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX - 3));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should hide the foreground surface beneath the background.
+        SCOPED_TRACE("after setLayer");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerShowHideWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before hide");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->hide());
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should hide the foreground surface.
+        SCOPED_TRACE("after hide, before show");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show());
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should show the foreground surface.
+        SCOPED_TRACE("after show");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetAlphaWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setAlpha");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75f));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should set foreground to be 75% opaque.
+        SCOPED_TRACE("after setAlpha");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 162,  63,  96);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetLayerStackWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setLayerStack");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayerStack(1));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should hide the foreground surface since it goes to a different
+        // layer stack.
+        SCOPED_TRACE("after setLayerStack");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetFlagsWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setFlags");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setFlags(
+            layer_state_t::eLayerHidden, layer_state_t::eLayerHidden));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        // This should hide the foreground surface
+        SCOPED_TRACE("after setFlags");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 75,  75,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, LayerSetMatrixWorks) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before setMatrix");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 91,  96, 195,  63,  63);
+        sc->checkPixel( 96, 101, 195,  63,  63);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setMatrix(M_SQRT1_2, M_SQRT1_2,
+            -M_SQRT1_2, M_SQRT1_2));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+    {
+        SCOPED_TRACE("after setMatrix");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 24,  24,  63,  63, 195);
+        sc->checkPixel( 91,  96, 195,  63,  63);
+        sc->checkPixel( 96,  91,  63,  63, 195);
+        sc->checkPixel(145, 145,  63,  63, 195);
+    }
+}
+
+TEST_F(LayerUpdateTest, DeferredTransactionTest) {
+    sp<ScreenCapture> sc;
+    {
+        SCOPED_TRACE("before anything");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96, 195,  63,  63);
+        sc->checkPixel(160, 160,  63,  63, 195);
+    }
+
+    // set up two deferred transactions on different frames
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(0.75));
+    mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+            mSyncSurfaceControl->getSurface()->getNextFrameNumber());
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(128,128));
+    mFGSurfaceControl->deferTransactionUntil(mSyncSurfaceControl->getHandle(),
+            mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1);
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    {
+        SCOPED_TRACE("before any trigger");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96, 195,  63,  63);
+        sc->checkPixel(160, 160,  63,  63, 195);
+    }
+
+    // should trigger the first deferred transaction, but not the second one
+    fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+    {
+        SCOPED_TRACE("after first trigger");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96, 162,  63,  96);
+        sc->checkPixel(160, 160,  63,  63, 195);
+    }
+
+    // should show up immediately since it's not deferred
+    SurfaceComposerClient::openGlobalTransaction();
+    ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setAlpha(1.0));
+    SurfaceComposerClient::closeGlobalTransaction(true);
+
+    // trigger the second deferred transaction
+    fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31);
+    {
+        SCOPED_TRACE("after second trigger");
+        ScreenCapture::captureScreen(&sc);
+        sc->checkPixel( 32,  32,  63,  63, 195);
+        sc->checkPixel( 96,  96,  63,  63, 195);
+        sc->checkPixel(160, 160, 195,  63,  63);
+    }
+}
+
 }
diff --git a/services/surfaceflinger/tests/resize/Android.mk b/services/surfaceflinger/tests/resize/Android.mk
deleted file mode 100644
index d81679e..0000000
--- a/services/surfaceflinger/tests/resize/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	resize.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-    libui \
-    libgui
-
-LOCAL_MODULE:= test-resize
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/resize/resize.cpp b/services/surfaceflinger/tests/resize/resize.cpp
deleted file mode 100644
index 8b051e8..0000000
--- a/services/surfaceflinger/tests/resize/resize.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * 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 <cutils/memory.h>
-
-#include <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-
-#include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
-
-using namespace android;
-
-namespace android {
-
-int main(int argc, char** argv)
-{
-    // set up the thread-pool
-    sp<ProcessState> proc(ProcessState::self());
-    ProcessState::self()->startThreadPool();
-
-    // create a client to surfaceflinger
-    sp<SurfaceComposerClient> client = new SurfaceComposerClient();
-    
-    sp<SurfaceControl> surfaceControl = client->createSurface(String8("resize"),
-            160, 240, PIXEL_FORMAT_RGB_565, 0);
-
-    sp<Surface> surface = surfaceControl->getSurface();
-
-    SurfaceComposerClient::openGlobalTransaction();
-    surfaceControl->setLayer(100000);
-    SurfaceComposerClient::closeGlobalTransaction();
-
-    ANativeWindow_Buffer outBuffer;
-    surface->lock(&outBuffer, NULL);
-    ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
-    android_memset16((uint16_t*)outBuffer.bits, 0xF800, bpr*outBuffer.height);
-    surface->unlockAndPost();
-
-    surface->lock(&outBuffer);
-    android_memset16((uint16_t*)outBuffer.bits, 0x07E0, bpr*outBuffer.height);
-    surface->unlockAndPost();
-
-    SurfaceComposerClient::openGlobalTransaction();
-    surfaceControl->setSize(320, 240);
-    SurfaceComposerClient::closeGlobalTransaction();
-
-    
-    IPCThreadState::self()->joinThreadPool();
-    
-    return 0;
-}
diff --git a/services/surfaceflinger/tests/screencap/Android.mk b/services/surfaceflinger/tests/screencap/Android.mk
deleted file mode 100644
index 5cdd1a8..0000000
--- a/services/surfaceflinger/tests/screencap/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	screencap.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-	libbinder \
-	libskia \
-    libui \
-    libgui
-
-LOCAL_MODULE:= test-screencap
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_C_INCLUDES += \
-	external/skia/include/core \
-	external/skia/include/effects \
-	external/skia/include/images \
-	external/skia/src/ports \
-	external/skia/include/utils
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/screencap/screencap.cpp b/services/surfaceflinger/tests/screencap/screencap.cpp
deleted file mode 100644
index f842fc3..0000000
--- a/services/surfaceflinger/tests/screencap/screencap.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * 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 <utils/Log.h>
-
-#include <binder/IPCThreadState.h>
-#include <binder/ProcessState.h>
-#include <binder/IServiceManager.h>
-
-#include <binder/IMemory.h>
-#include <gui/ISurfaceComposer.h>
-
-#include <SkImageEncoder.h>
-#include <SkBitmap.h>
-
-using namespace android;
-
-int main(int argc, char** argv)
-{
-    if (argc != 2) {
-        printf("usage: %s path\n", argv[0]);
-        exit(0);
-    }
-
-    const String16 name("SurfaceFlinger");
-    sp<ISurfaceComposer> composer;
-    getService(name, &composer);
-
-    sp<IMemoryHeap> heap;
-    uint32_t w, h;
-    PixelFormat f;
-    sp<IBinder> display(composer->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
-    status_t err = composer->captureScreen(display, &heap, &w, &h, &f, 0, 0);
-    if (err != NO_ERROR) {
-        fprintf(stderr, "screen capture failed: %s\n", strerror(-err));
-        exit(0);
-    }
-
-    printf("screen capture success: w=%u, h=%u, pixels=%p\n",
-            w, h, heap->getBase());
-
-    printf("saving file as PNG in %s ...\n", argv[1]);
-
-    SkBitmap b;
-    b.setConfig(SkBitmap::kARGB_8888_Config, w, h);
-    b.setPixels(heap->getBase());
-    SkImageEncoder::EncodeFile(argv[1], b,
-            SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
-
-    return 0;
-}
diff --git a/services/surfaceflinger/tests/transform/Android.mk b/services/surfaceflinger/tests/transform/Android.mk
deleted file mode 100644
index 6219dae..0000000
--- a/services/surfaceflinger/tests/transform/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-	TransformTest.cpp \
-	../../Transform.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-	libcutils \
-	libutils \
-	libui \
-
-LOCAL_MODULE:= test-transform
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_C_INCLUDES += ../..
-
-include $(BUILD_EXECUTABLE)
diff --git a/services/surfaceflinger/tests/transform/TransformTest.cpp b/services/surfaceflinger/tests/transform/TransformTest.cpp
deleted file mode 100644
index e112c4e..0000000
--- a/services/surfaceflinger/tests/transform/TransformTest.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * 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 <utils/Errors.h>
-#include "../../Transform.h"
-
-using namespace android;
-
-int main(int argc, char **argv)
-{
-    Transform tr90(Transform::ROT_90);
-    Transform trFH(Transform::FLIP_H);
-    Transform trFV(Transform::FLIP_V);
-
-    Transform tr90FH(Transform::ROT_90 | Transform::FLIP_H);
-    Transform tr90FV(Transform::ROT_90 | Transform::FLIP_V);
-
-    tr90.dump("tr90");
-    trFH.dump("trFH");
-    trFV.dump("trFV");
-
-    tr90FH.dump("tr90FH");
-    tr90FV.dump("tr90FV");
-
-    (trFH*tr90).dump("trFH*tr90");
-    (trFV*tr90).dump("trFV*tr90");
-
-    (tr90*trFH).dump("tr90*trFH");
-    (tr90*trFV).dump("tr90*trFV");
-
-    return 0;
-}
diff --git a/vulkan/.clang-format b/vulkan/.clang-format
new file mode 100644
index 0000000..563cd9a
--- /dev/null
+++ b/vulkan/.clang-format
@@ -0,0 +1,2 @@
+BasedOnStyle: Chromium
+IndentWidth: 4
diff --git a/vulkan/Android.mk b/vulkan/Android.mk
new file mode 100644
index 0000000..d125673
--- /dev/null
+++ b/vulkan/Android.mk
@@ -0,0 +1 @@
+include $(call all-named-subdir-makefiles, libvulkan nulldrv tools)
diff --git a/vulkan/README.md b/vulkan/README.md
new file mode 100644
index 0000000..9fba728
--- /dev/null
+++ b/vulkan/README.md
@@ -0,0 +1,28 @@
+# frameworks/native/vulkan
+
+This subdirectory contains Android's Vulkan loader, as well as some Vulkan-related tools useful to platform developers.
+
+## Coding Style
+
+We follow the [Chromium coding style](https://www.chromium.org/developers/coding-style) for naming and formatting, except with four-space indentation instead of two spaces. In general, any C++ features supported by the prebuilt platform toolchain are allowed.
+
+Use "clang-format -style=file" to format all C/C++ code, except code imported verbatim from elsewhere. Setting up git-clang-format in your environment is recommended.
+
+## Code Generation
+
+We generate several parts of the loader and tools from a Vulkan API description file, stored in `api/vulkan.api`. Code generation must be done manually because the generator tools aren't part of the platform toolchain (yet?). Files named `foo_gen.*` are generated from the API file and a template file named `foo.tmpl`.
+
+ To run the generator:
+
+### One-time setup
+- Install [golang](https://golang.org/), if you don't have it already.
+- Create a directory (e.g. `$HOME/lib/go`) for local go sources and binaries and add it to `$GOPATH`.
+- `$ git clone https://android.googlesource.com/platform/tools/gpu $GOPATH/src/android.googlesource.com/platform/tools/gpu`
+- `$ go get android.googlesource.com/platform/tools/gpu/api/...`
+- You should now have `$GOPATH/bin/apic`. You might want to add `$GOPATH/bin` to your `$PATH`.
+
+### Generating code
+To generate `libvulkan/*_gen.*`,
+- `$ cd libvulkan`
+- `$ apic template ../api/vulkan.api code-generator.tmpl`
+Similar for `nulldrv/null_driver_gen.*`.
diff --git a/vulkan/api/platform.api b/vulkan/api/platform.api
new file mode 100644
index 0000000..7aa19e7
--- /dev/null
+++ b/vulkan/api/platform.api
@@ -0,0 +1,50 @@
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are 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 Materials.
+//
+// THE MATERIALS ARE 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
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+// Platform types, as defined or included in vk_platform.h
+
+type u64 size_t
+
+// VK_USE_PLATFORM_XLIB_KHR
+@internal class Display {}
+@internal class Window {}
+@internal type u64 VisualID
+
+// VK_USE_PLATFORM_XCB_KHR
+@internal class xcb_connection_t {}
+@internal type u32 xcb_window_t
+@internal type u32 xcb_visualid_t
+
+// VK_USE_PLATFORM_WAYLAND_KHR
+@internal class wl_display {}
+@internal class wl_surface {}
+
+// VK_USE_PLATFORM_MIR_KHR
+@internal class MirConnection {}
+@internal class MirSurface {}
+
+// VK_USE_PLATFORM_ANDROID_KHR
+@internal class ANativeWindow {}
+@internal type void* buffer_handle_t
+
+// VK_USE_PLATFORM_WIN32_KHR
+@internal type void* HINSTANCE
+@internal type void* HWND
diff --git a/vulkan/api/templates/asciidoc.tmpl b/vulkan/api/templates/asciidoc.tmpl
new file mode 100644
index 0000000..3009e19
--- /dev/null
+++ b/vulkan/api/templates/asciidoc.tmpl
@@ -0,0 +1,151 @@
+{{Include "vulkan_common.tmpl"}}
+{{if not (Global "AsciiDocPath")}}{{Global "AsciiDocPath" "../../doc/specs/vulkan/"}}{{end}}
+{{$ | Macro "AsciiDoc.Main"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  AsciiDoc generation main entry point.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Main"}}
+  {{$docPath := Global "AsciiDocPath"}}
+
+  {{/* Generate AsciiDoc files for API enums and bitfields (flags). */}}
+  {{range $e := $.Enums}}
+    {{if not $e.IsBitfield}}
+      {{$filename := print $docPath "enums/" (Macro "EnumName" $e) ".txt"}}
+      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Enum" $e) "File" $filename}}
+    {{else}}
+      {{$filename := print $docPath "flags/" (Macro "EnumName" $e) ".txt"}}
+      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Flag" $e) "File" $filename}}
+    {{end}}
+  {{end}}
+
+  {{/* Generate AsciiDoc files for API commands (protos). */}}
+  {{range $f := (AllCommands $)}}
+    {{if not (GetAnnotation $f "pfn")}}
+      {{$filename := print $docPath "protos/" $f.Name ".txt"}}
+      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Proto" $f) "File" $filename}}
+    {{end}}
+  {{end}}
+
+  {{/* Generate AsciiDoc files for API structs. */}}
+  {{range $c := $.Classes}}
+    {{if not (GetAnnotation $c "internal")}}
+      {{$filename := print $docPath "structs/" $c.Name ".txt"}}
+      {{Macro "AsciiDoc.Write" "Code" (Macro "AsciiDoc.Struct" $c) "File" $filename}}
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the AsciiDoc contents for the specified API enum.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Enum"}}
+  {{AssertType $ "Enum"}}
+
+  {{Macro "Docs" $.Docs}}
+  typedef enum {
+    {{range $i, $e := $.Entries}}
+      {{Macro "EnumEntry" $e}} = {{AsSigned $e.Value}}, {{Macro "Docs" $e.Docs}}
+    {{end}}
+  ¶
+    {{$name := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
+    {{$first := Macro "EnumFirstEntry" $}}
+    {{$last  := Macro "EnumLastEntry" $}}
+    {{$name}}_BEGIN_RANGE = {{$first}},
+    {{$name}}_END_RANGE = {{$last}},
+    {{$name}}_NUM = ({{$last}} - {{$first}} + 1),
+    {{$name}}_MAX_ENUM = 0x7FFFFFFF
+  } {{Macro "EnumName" $}};
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the AsciiDoc contents for the specified API bitfield.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Flag"}}
+  {{AssertType $ "Enum"}}
+
+  {{Macro "Docs" $.Docs}}
+  typedef VkFlags {{Macro "EnumName" $}};
+  {{if $.Entries}}
+  typedef enum {
+  {{range $e := $.Entries}}
+    {{Macro "BitfieldEntryName" $e}} = {{printf "%#.8x" $e.Value}}, {{Macro "Docs" $e.Docs}}
+  {{end}}
+  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
+  {{end}}
+{{end}}
+
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the AsciiDoc contents for the specified API class.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Struct"}}
+  {{AssertType $ "Class"}}
+
+  {{Macro "Docs" $.Docs}}
+  typedef {{if GetAnnotation $ "union"}}union{{else}}struct{{end}} {
+    {{range $f := $.Fields}}
+      {{Node "Type" $f}} {{$f.Name}}{{Macro "ArrayPostfix" (TypeOf $f)}}; {{Macro "Docs" $f.Docs}}
+    {{end}}
+  } {{Macro "StructName" $}};
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the AsciiDoc contents for the specified API function.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Proto"}}
+  {{AssertType $ "Function"}}
+
+  {{Macro "Docs" $.Docs}}
+  {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Wraps the specified Code in AsciiDoc source tags then writes to the specified File.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Write"}}
+  {{AssertType $.Code "string"}}
+  {{AssertType $.File "string"}}
+
+  {{$code := $.Code | Format (Global "clang-format")}}
+  {{JoinWith "\n" (Macro "AsciiDoc.Header") $code (Macro "AsciiDoc.Footer") ""| Write $.File}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits an AsciiDoc source header.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Header"}}
+[source,{basebackend@docbook:c++:cpp}]
+------------------------------------------------------------------------------
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits an AsciiDoc source footer.
+-------------------------------------------------------------------------------
+*/}}
+{{define "AsciiDoc.Footer"}}
+------------------------------------------------------------------------------
+{{end}}
diff --git a/vulkan/api/templates/vk_xml.tmpl b/vulkan/api/templates/vk_xml.tmpl
new file mode 100644
index 0000000..893bde7
--- /dev/null
+++ b/vulkan/api/templates/vk_xml.tmpl
@@ -0,0 +1,435 @@
+{{Include "vulkan_common.tmpl"}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "vk.xml" | Reflow 4 | Write "vk.xml"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Entry point
+-------------------------------------------------------------------------------
+*/}}
+{{define "vk.xml"}}
+<?xml version="1.0" encoding="UTF-8"?>
+<registry>
+    »<comment>«
+Copyright (c) 2015 The Khronos Group Inc.

+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are 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 Materials.

+THE MATERIALS ARE 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
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.

+------------------------------------------------------------------------

+This file, vk.xml, is the Vulkan API Registry.»
+    </comment>

+    <!-- SECTION: Vulkan type definitions -->
+    <types>»
+        <type name="vk_platform" category="include">#include "vk_platform.h"</type>

+        <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
+    «((major &lt;&lt; 22) | (minor &lt;&lt; 12) | patch)</type>»

+        <type category="define">// Vulkan API version supported by this file««
+#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})</type>

+        »»<type category="define">««
+#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
+#define <name>VK_NONDISP_HANDLE_OPERATOR_BOOL</name>() explicit operator bool() const { return handle != 0; }
+#else
+#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
+«#endif
+      »»»</type>

+      <type category="define">«««
+#define <name>VK_DEFINE_HANDLE</name>(obj) typedef struct obj##_T* obj;</type>
+      »»»<type category="define">«««
+#if defined(__cplusplus)
+    »»#if (_MSC_VER &gt;= 1800 || __cplusplus &gt;= 201103L)
+        »// The bool operator only works if there are no implicit conversions from an obj to
+        // a bool-compatible type, which can then be used to unintentionally violate type safety.
+        // C++11 and above supports the "explicit" keyword on conversion operators to stop this
+        // from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
+        // the object handle as a bool in expressions like:
+        //     if (obj) vkDestroy(obj);
+        #define VK_NONDISP_HANDLE_OPERATOR_BOOL() explicit operator bool() const { return handle != 0; }
+        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
+            explicit obj(uint64_t x) : handle(x) { } \
+            obj(decltype(nullptr)) : handle(0) { }
+    «#else»
+        #define VK_NONDISP_HANDLE_OPERATOR_BOOL()
+        #define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
+            obj(uint64_t x) : handle(x) { }
+    «#endif
+    #define <name>VK_DEFINE_NONDISP_HANDLE</name>(obj) \»
+        struct obj { \
+            obj() { } \
+            VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
+            obj&amp; operator =(uint64_t x) { handle = x; return *this; } \
+            bool operator==(const obj&amp; other) const { return handle == other.handle; } \
+            bool operator!=(const obj&amp; other) const { return handle != other.handle; } \
+            bool operator!() const { return !handle; } \
+            VK_NONDISP_HANDLE_OPERATOR_BOOL() \
+            uint64_t handle; \
+        };
+««#else
+    »#define VK_DEFINE_NONDISP_HANDLE(obj) typedef struct obj##_T { uint64_t handle; } obj;«
+#endif
+        »»</type>

+        <type category="define">
+#if defined(__cplusplus) &amp;&amp; ((defined(_MSC_VER) &amp;&amp; _MSC_VER &gt;= 1800) || __cplusplus &gt;= 201103L)
+    »#define <name>VK_NULL_HANDLE</name> nullptr
+«#else
+    »#define VK_NULL_HANDLE 0
+«#endif
+        »»</type>

+        <type requires="vk_platform" name="VkDeviceSize"/>
+        <type requires="vk_platform" name="VkSampleMask"/>
+        <type requires="vk_platform" name="VkFlags"/>
+        <!-- Basic C types, pulled in via vk_platform.h -->
+        <type requires="vk_platform" name="char"/>
+        <type requires="vk_platform" name="float"/>
+        <type requires="vk_platform" name="VkBool32"/>
+        <type requires="vk_platform" name="uint8_t"/>
+        <type requires="vk_platform" name="uint32_t"/>
+        <type requires="vk_platform" name="uint64_t"/>
+        <type requires="vk_platform" name="int32_t"/>
+        <type requires="vk_platform" name="size_t"/>
+        <!-- Bitfield types -->
+        {{range $e := $.Enums}}
+          {{if $e.IsBitfield}}
+            {{$bits := print (Macro "EnumName" $e | TrimRight "s") "Bits"}}
+            <type{{if $e.Entries}} requires="{{$bits}}"{{end}} category="bitmask">typedef <type>VkFlags</type> <name>{{$e.Name}}</name>;</type>§
+            {{if $e.Entries}}{{Macro "XML.Docs" $e.Docs}}
+            {{else}}{{Macro "XML.Docs" (Strings $e.Docs "(no bits yet)")}}
+            {{end}}
+          {{end}}
+        {{end}}

+        <!-- Types which can be void pointers or class pointers, selected at compile time -->
+        {{range $i, $p := $.Pseudonyms}}
+          {{     if (GetAnnotation $p "dispatchHandle")}}
+            {{if Global "VK_DEFINE_HANDLE_TYPE_DEFINED"}}
+              <type category="handle">VK_DEFINE_HANDLE(<name>{{$p.Name}}</name>)</type>
+            {{else}}
+              {{Global "VK_DEFINE_HANDLE_TYPE_DEFINED" "YES"}}
+              <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
+            {{end}}
+          {{else if (GetAnnotation $p "nonDispatchHandle")}}
+            {{if Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED"}}
+              <type category="handle">VK_DEFINE_NONDISP_HANDLE(<name>{{$p.Name}}</name>)</type>
+            {{else}}
+              {{Global "VK_DEFINE_NONDISP_HANDLE_TYPE_DEFINED" "YES"}}
+              <type category="handle"><type>VK_DEFINE_NONDISP_HANDLE</type>(<name>{{$p.Name}}</name>)</type>
+            {{end}}
+          {{end}}
+        {{end}}

+        <!-- Types generated from corresponding <enums> tags below -->
+        {{range $e := SortBy $.Enums "EnumName"}}
+          {{if and $e.Entries (not (GetAnnotation $e "internal"))}}
+            {{if $e.IsBitfield}}
+              <type name="{{Macro "EnumName" $e | TrimRight "s"}}Bits" category="enum"/>
+            {{else}}
+              <type name="{{$e.Name}}" category="enum"/>
+            {{end}}
+          {{end}}
+        {{end}}

+        <!-- The PFN_vk*Function types are used by VkAllocCallbacks below -->
+        <type>typedef void* (VKAPI *<name>PFN_vkAllocFunction</name>)(«
+          void*                           pUserData,
+          size_t                          size,
+          size_t                          alignment,
+          <type>VkSystemAllocType</type>               allocType);</type>»
+        <type>typedef void (VKAPI *<name>PFN_vkFreeFunction</name>)(«
+          void*                           pUserData,
+          void*                           pMem);</type>»

+        <!-- The PFN_vkVoidFunction type are used by VkGet*ProcAddr below -->
+        <type>typedef void (VKAPI *<name>PFN_vkVoidFunction</name>)(void);</type>

+        <!-- Struct types -->
+        {{range $c := $.Classes}}
+          {{if not (GetAnnotation $c "internal")}}
+            {{Macro "Struct" $c}}
+          {{end}}
+        {{end}}
+    «</types>

+    <!-- SECTION: Vulkan enumerant (token) definitions. -->

+    <enums namespace="VK" comment="Misc. hardcoded constants - not an enumerated type">»
+            <!-- This is part of the header boilerplate -->
+      {{range $d := $.Definitions}}
+        {{if HasPrefix $d.Name "VK_"}}
+        <enum value="{{$d.Expression}}"        name="{{$d.Name}}"/>{{Macro "XML.Docs" $d.Docs}}
+        {{end}}
+      {{end}}
+        <enum value="1000.0f"  name="VK_LOD_CLAMP_NONE"/>
+        <enum value="(-0U)" name="VK_REMAINING_MIP_LEVELS"/>
+        <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
+        <enum value="(_0ULL)" name="VK_WHOLE_SIZE"/>
+        <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
+        <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
+        <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
+    «</enums>

+    <!-- Unlike OpenGL, most tokens in Vulkan are actual typed enumerants in»
+         their own numeric namespaces. The "name" attribute is the C enum
+         type name, and is pulled in from a <type> definition above
+         (slightly clunky, but retains the type / enum distinction). "type"
+         attributes of "enum" or "bitmask" indicate that these values should
+         be generated inside an appropriate definition. -->«

+    {{range $e := $.Enums}}
+      {{if not (or $e.IsBitfield (GetAnnotation $e "internal"))}}
+        {{Macro "XML.Enum" $e}}
+      {{end}}
+    {{end}}

+    <!-- Flags -->
+    {{range $e := $.Enums}}
+      {{if $e.IsBitfield}}
+        {{Macro "XML.Bitfield" $e}}
+      {{end}}
+    {{end}}

+    <!-- SECTION: Vulkan command definitions -->
+    <commands namespace="vk">»
+    {{range $f := AllCommands $}}
+      {{if not (GetAnnotation $f "pfn")}}
+        {{Macro "XML.Function" $f}}
+      {{end}}
+    {{end}}
+    «</commands>

+    <!-- SECTION: Vulkan API interface definitions -->
+    <feature api="vulkan" name="VK_VERSION_1_0" number="1.0">»
+        <require comment="Header boilerplate">»
+            <type name="vk_platform"/>
+        «</require>
+        <require comment="API version">»
+            <type name="VK_API_VERSION"/>
+        «</require>
+        <require comment="API constants">»
+            <enum name="VK_LOD_CLAMP_NONE"/>
+            <enum name="VK_REMAINING_MIP_LEVELS"/>
+            <enum name="VK_REMAINING_ARRAY_LAYERS"/>
+            <enum name="VK_WHOLE_SIZE"/>
+            <enum name="VK_ATTACHMENT_UNUSED"/>
+            <enum name="VK_TRUE"/>
+            <enum name="VK_FALSE"/>
+        «</require>
+        <require comment="All functions (TODO: split by type)">»
+        {{range $f := AllCommands $}}
+          {{if not (GetAnnotation $f "pfn")}}
+          <command name="{{$f.Name}}"/>
+          {{end}}
+        {{end}}
+        </require>
+        «<require comment="Types not directly used by the API">»
+            <!-- Include <type name="typename"/> here for e.g. structs that»
+                 are not parameter types of commands, but still need to be
+                 defined in the API.
+             «-->
+            <type name="VkBufferMemoryBarrier"/>
+            <type name="VkDispatchIndirectCmd"/>
+            <type name="VkDrawIndexedIndirectCmd"/>
+            <type name="VkDrawIndirectCmd"/>
+            <type name="VkImageMemoryBarrier"/>
+            <type name="VkMemoryBarrier"/>
+        «</require>
+    «</feature>

+    <!-- SECTION: Vulkan extension interface definitions (none yet) -->
+«</registry>
+{{end}}
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified bitfield.
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Bitfield"}}
+  {{AssertType $ "Enum"}}
+
+  {{if $.Entries}}
+  <enums namespace="VK" name="{{Macro "EnumName" $ | TrimRight "s"}}Bits" type="bitmask">»
+  {{range $e := $.Entries}}
+    {{$pos := Bitpos $e.Value}}
+    <enum §
+      {{if gt $pos -1}} bitpos="{{$pos}}"    §
+      {{else}}value="{{if $e.Value}}{{printf "0x%.8X" $e.Value}}{{else}}0{{end}}"    §
+      {{end}}name="{{Macro "BitfieldEntryName" $e}}" §
+      {{if $d := $e.Docs}} comment="{{$d | JoinWith "  "}}"{{end}}/>
+  {{end}}
+  «</enums>
+  {{end}}
+
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified enum.
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Enum"}}
+  {{AssertType $ "Enum"}}
+
+  <enums namespace="VK" name="{{Macro "EnumName" $}}" type="enum" §
+         expand="{{Macro "EnumName" $ | SplitPascalCase | Upper | JoinWith "_"}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
+  {{range $i, $e := $.Entries}}
+    <enum value="{{AsSigned $e.Value}}"     name="{{Macro "BitfieldEntryName" $e}}"{{if $e.Docs}} comment="{{$e.Docs | JoinWith "  "}}"{{end}}/>
+  {{end}}
+  {{if $lu := GetAnnotation $ "lastUnused"}}
+    <unused start="{{index $lu.Arguments 0}}"/>
+  {{end}}
+  «</enums>
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified class.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Struct"}}
+  {{AssertType $ "Class"}}
+
+  <type category="{{Macro "StructType" $}}" name="{{Macro "StructName" $}}"{{if $.Docs}} comment="{{$.Docs | JoinWith "  "}}"{{end}}>»
+    {{range $f := $.Fields}}
+    <member>{{Node "XML.Type" $f}}        <name>{{$f.Name}}</name>{{Macro "XML.ArrayPostfix" $f}}</member>{{Macro "XML.Docs" $f.Docs}}
+    {{end}}
+  «</type>
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits either 'struct' or 'union' for the specified class.
+-------------------------------------------------------------------------------
+*/}}
+{{define "StructType"}}
+  {{AssertType $ "Class"}}
+
+  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C function pointer typedef declaration for the specified command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Function"}}
+  {{AssertType $ "Function"}}
+
+    {{$ts := GetAnnotation $ "threadSafety"}}
+    <command{{if $ts}} threadsafe="{{index $ts.Arguments 0}}"{{end}}>»
+        <proto>{{Node "XML.Type" $.Return}} <name>{{$.Name}}</name></proto>
+        {{range $p := $.CallParameters}}
+          <param>{{Node "XML.Type" $p}} <name>{{$p.Name}}{{Macro "ArrayPostfix" $p}}</name></param>
+        {{end}}
+    «</command>
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the XML translation for the specified documentation block (string array).
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Docs"}}
+  {{if $}} <!-- {{JoinWith "  " $ | Replace "<" "" | Replace ">" ""}} -->{{end}}
+{{end}}
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C translation for the specified type.
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Type.Class"      }}<type>{{Macro "StructName" $.Type}}</type>{{end}}
+{{define "XML.Type.Pseudonym"  }}<type>{{$.Type.Name}}</type>{{end}}
+{{define "XML.Type.Enum"       }}<type>{{$.Type.Name}}</type>{{end}}
+{{define "XML.Type.StaticArray"}}{{Node "XML.Type" $.Type.ValueType}}{{end}}
+{{define "XML.Type.Pointer"    }}{{if $.Type.Const}}{{Node "XML.ConstType" $.Type.To}}{{else}}{{Node "XML.Type" $.Type.To}}{{end}}*{{end}}
+{{define "XML.Type.Slice"      }}<type>{{Node "XML.Type" $.Type.To}}</type>*{{end}}
+{{define "XML.Type#s8"         }}<type>int8_t</type>{{end}}
+{{define "XML.Type#u8"         }}<type>uint8_t</type>{{end}}
+{{define "XML.Type#s16"        }}<type>int16_t</type>{{end}}
+{{define "XML.Type#u16"        }}<type>uint16_t</type>{{end}}
+{{define "XML.Type#s32"        }}<type>int32_t</type>{{end}}
+{{define "XML.Type#u32"        }}<type>uint32_t</type>{{end}}
+{{define "XML.Type#f32"        }}<type>float</type>{{end}}
+{{define "XML.Type#s64"        }}<type>int64_t</type>{{end}}
+{{define "XML.Type#u64"        }}<type>uint64_t</type>{{end}}
+{{define "XML.Type#f64"        }}<type>double</type>{{end}}
+{{define "XML.Type#char"       }}<type>char</type>{{end}}
+{{define "XML.Type#void"       }}void{{end}}
+
+{{define "XML.ConstType_Default"}}const {{Node "XML.Type" $.Type}}{{end}}
+{{define "XML.ConstType.Pointer"}}{{Node "XML.Type" $.Type}} const{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a C type and name for the given parameter
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Parameter"}}
+  {{AssertType $ "Parameter"}}
+
+  <type>{{Macro "ParameterType" $}}</type> <name>{{$.Name}}{{Macro "ArrayPostfix" $}}</name>
+{{end}}
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a comma-separated list of C type-name paired parameters for the given
+  command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.Parameters"}}
+  {{AssertType $ "Function"}}
+
+  {{ForEach $.CallParameters "XML.Parameter" | JoinWith ", "}}
+  {{if not $.CallParameters}}<type>void</type>{{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the fixed-size-array postfix for pseudonym types annotated with @array
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.ArrayPostfix"}}{{Node "XML.ArrayPostfix" $}}{{end}}
+{{define "XML.ArrayPostfix.StaticArray"}}[{{Node "XML.NamedValue" $.Type.SizeExpr}}]{{end}}
+{{define "XML.ArrayPostfix_Default"}}{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the value of the given constant, or the <enum> tagged name if existant.
+-------------------------------------------------------------------------------
+*/}}
+{{define "XML.NamedValue.Definition"}}<enum>{{$.Node.Name}}</enum>{{end}}
+{{define "XML.NamedValue.EnumEntry"}}<enum>{{$.Node.Name}}</enum>{{end}}
+{{define "XML.NamedValue_Default"}}{{$.Node}}{{end}}
diff --git a/vulkan/api/templates/vulkan_common.tmpl b/vulkan/api/templates/vulkan_common.tmpl
new file mode 100644
index 0000000..f694c56
--- /dev/null
+++ b/vulkan/api/templates/vulkan_common.tmpl
@@ -0,0 +1,223 @@
+{{$clang_style := "{BasedOnStyle: Google, AccessModifierOffset: -4, ColumnLimit: 200, ContinuationIndentWidth: 8, IndentWidth: 4, AlignOperands: true, CommentPragmas: '.*'}"}}
+{{Global "clang-format" (Strings "clang-format" "-style" $clang_style)}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C translation for the specified type.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Type.Class"      }}{{if GetAnnotation $.Type "internal"}}struct {{end}}{{Macro "StructName" $.Type}}{{end}}
+{{define "Type.Pseudonym"  }}{{$.Type.Name}}{{end}}
+{{define "Type.Enum"       }}{{$.Type.Name}}{{end}}
+{{define "Type.StaticArray"}}{{Node "Type" $.Type.ValueType}}{{end}}
+{{define "Type.Pointer"    }}{{if $.Type.Const}}{{Node "ConstType" $.Type.To}}{{else}}{{Node "Type" $.Type.To}}{{end}}*{{end}}
+{{define "Type.Slice"      }}{{Log "%T %+v" $.Node $.Node}}{{Node "Type" $.Type.To}}*{{end}}
+{{define "Type#bool"       }}bool{{end}}
+{{define "Type#int"        }}int{{end}}
+{{define "Type#uint"       }}unsigned int{{end}}
+{{define "Type#s8"         }}int8_t{{end}}
+{{define "Type#u8"         }}uint8_t{{end}}
+{{define "Type#s16"        }}int16_t{{end}}
+{{define "Type#u16"        }}uint16_t{{end}}
+{{define "Type#s32"        }}int32_t{{end}}
+{{define "Type#u32"        }}uint32_t{{end}}
+{{define "Type#f32"        }}float{{end}}
+{{define "Type#s64"        }}int64_t{{end}}
+{{define "Type#u64"        }}uint64_t{{end}}
+{{define "Type#f64"        }}double{{end}}
+{{define "Type#void"       }}void{{end}}
+{{define "Type#char"       }}char{{end}}
+
+{{define "ConstType_Default"}}const {{Node "Type" $.Type}}{{end}}
+{{define "ConstType.Pointer"}}{{Node "Type" $.Type}} const{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C translation for the specified documentation block (string array).
+-------------------------------------------------------------------------------
+*/}}
+{{define "Docs"}}
+  {{if $}}// {{$ | JoinWith "\n// "}}{{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of a bitfield entry.
+-------------------------------------------------------------------------------
+*/}}
+{{define "BitfieldEntryName"}}
+  {{AssertType $ "EnumEntry"}}
+
+  {{Macro "EnumEntry" $}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of an enum type.
+-------------------------------------------------------------------------------
+*/}}
+{{define "EnumName"}}{{AssertType $ "Enum"}}{{$.Name}}{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of an enum entry.
+-------------------------------------------------------------------------------
+*/}}
+{{define "EnumEntry"}}
+  {{AssertType $.Owner "Enum"}}
+  {{AssertType $.Name "string"}}
+
+  {{$.Name}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of the first entry of an enum.
+-------------------------------------------------------------------------------
+*/}}
+{{define "EnumFirstEntry"}}
+  {{AssertType $ "Enum"}}
+
+  {{range $i, $e := $.Entries}}
+    {{if not $i}}{{$e.Name}}{{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of the last entry of an enum.
+-------------------------------------------------------------------------------
+*/}}{{define "EnumLastEntry"}}
+  {{AssertType $ "Enum"}}
+
+  {{range $i, $e := $.Entries}}
+    {{if not (HasMore $i $.Entries)}}{{$e.Name}}{{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of a struct (class) type.
+-------------------------------------------------------------------------------
+*/}}
+{{define "StructName"}}{{AssertType $ "Class"}}{{$.Name}}{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the name of a function.
+-------------------------------------------------------------------------------
+*/}}
+{{define "FunctionName"}}{{AssertType $ "Function"}}{{$.Name}}{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the fixed-size-array postfix for pseudonym types annotated with @array
+-------------------------------------------------------------------------------
+*/}}
+{{define "ArrayPostfix"}}{{Node "ArrayPostfix" $}}{{end}}
+{{define "ArrayPostfix.StaticArray"}}[{{$.Type.Size}}]{{end}}
+{{define "ArrayPostfix_Default"}}{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a C type and name for the given parameter
+-------------------------------------------------------------------------------
+*/}}
+{{define "Parameter"}}
+  {{AssertType $ "Parameter"}}
+
+  {{if GetAnnotation $ "readonly"}}const {{end}}{{Macro "ParameterType" $}} {{$.Name}}{{Macro "ArrayPostfix" $}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a C name for the given parameter
+-------------------------------------------------------------------------------
+*/}}
+{{define "ParameterName"}}
+  {{AssertType $ "Parameter"}}
+
+  {{$.Name}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a C type for the given parameter
+-------------------------------------------------------------------------------
+*/}}
+{{define "ParameterType"}}{{AssertType $ "Parameter"}}{{Node "Type" $}}{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a comma-separated list of C type-name paired parameters for the given
+  command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Parameters"}}
+  {{AssertType $ "Function"}}
+
+  {{ForEach $.CallParameters "Parameter" | JoinWith ", "}}
+  {{if not $.CallParameters}}void{{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C function pointer name for the specified command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "FunctionPtrName"}}
+  {{AssertType $ "Function"}}
+
+  PFN_{{$.Name}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Parses const variables as text Globals.
+-------------------------------------------------------------------------------
+*/}}
+{{define "DefineGlobals"}}
+  {{AssertType $ "API"}}
+
+  {{range $d := $.Definitions}}
+    {{Global $d.Name $d.Expression}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Given a function, return "Global", "Instance", or "Device" depending on which
+  dispatch table the function belongs to.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Vtbl#VkInstance"      }}Instance{{end}}
+{{define "Vtbl#VkPhysicalDevice"}}Instance{{end}}
+{{define "Vtbl#VkDevice"        }}Device{{end}}
+{{define "Vtbl#VkQueue"         }}Device{{end}}
+{{define "Vtbl#VkCommandBuffer" }}Device{{end}}
+{{define "Vtbl_Default"         }}Global{{end}}
+{{define "Vtbl"}}
+  {{AssertType $ "Function"}}
+
+  {{if gt (len $.CallParameters) 0}}
+    {{Node "Vtbl" (index $.CallParameters 0)}}
+  {{else}}Global
+  {{end}}
+{{end}}
diff --git a/vulkan/api/templates/vulkan_h.tmpl b/vulkan/api/templates/vulkan_h.tmpl
new file mode 100644
index 0000000..83a5e40
--- /dev/null
+++ b/vulkan/api/templates/vulkan_h.tmpl
@@ -0,0 +1,295 @@
+{{Include "vulkan_common.tmpl"}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "vulkan.h" | Format (Global "clang-format") | Write "../include/vulkan.h"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Entry point
+-------------------------------------------------------------------------------
+*/}}
+{{define "vulkan.h"}}
+#ifndef __vulkan_h_
+#define __vulkan_h_ 1

+#ifdef __cplusplus
+extern "C" {
+#endif

+/*
+** Copyright (c) 2015-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/

+/*
+** This header is generated from the Khronos Vulkan API Registry.
+**
+*/

+#define VK_VERSION_1_0 1
+#include "vk_platform.h"

+#define VK_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch))

+// Vulkan API version supported by this file
+#define VK_API_VERSION \
+    VK_MAKE_VERSION({{Global "VERSION_MAJOR"}}, {{Global "VERSION_MINOR"}}, {{Global "VERSION_PATCH"}})

+#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
+#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
+#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)

+#if defined(__cplusplus) && ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
+    #define VK_NULL_HANDLE nullptr
+#else
+    #define VK_NULL_HANDLE 0
+#endif

+#define VK_DEFINE_HANDLE(obj) typedef struct obj##_T* obj;

+#if defined(__cplusplus)
+#if ((defined(_MSC_VER) && _MSC_VER >= 1800 || __cplusplus >= 201103L)
+// The bool operator only works if there are no implicit conversions from an obj to
+// a bool-compatible type, which can then be used to unintentionally violate type safety.
+// C++11 and above supports the "explicit" keyword on conversion operators to stop this
+// from happening. Otherwise users of C++ below C++11 won't get direct access to evaluating
+// the object handle as a bool in expressions like:
+//     if (obj) vkDestroy(obj);
+#define VK_NONDISP_HANDLE_OPERATOR_BOOL() \
+    explicit operator bool() const { return handle != 0; }
+#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
+    explicit obj(uint64_t x) : handle(x) { } \
+    obj(decltype(nullptr)) : handle(0) { }
+#else
+#define VK_NONDISP_HANDLE_OPERATOR_BOOL()
+#define VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj) \
+    obj(uint64_t x) : handle(x) { }
+#endif
+#define VK_DEFINE_NONDISP_HANDLE(obj)                                              \
+    struct obj {                                                                   \
+        obj() : handle(0) { }                                                      \
+        VK_NONDISP_HANDLE_CONSTRUCTOR_FROM_UINT64(obj)                             \
+        obj& operator=(uint64_t x) {                                               \
+            handle = x;                                                            \
+            return *this;                                                          \
+        }                                                                          \
+        bool operator==(const obj& other) const { return handle == other.handle; } \
+        bool operator!=(const obj& other) const { return handle != other.handle; } \
+        bool operator!() const { return !handle; }                                 \
+        VK_NONDISP_HANDLE_OPERATOR_BOOL()                                          \
+        uint64_t handle;                                                           \
+    };
+#else
+#define VK_DEFINE_NONDISP_HANDLE(obj) \
+    typedef struct obj##_T { uint64_t handle; } obj;
+#endif

+#define VK_LOD_CLAMP_NONE         1000.0f
+#define VK_REMAINING_MIP_LEVELS   (~0U)
+#define VK_REMAINING_ARRAY_LAYERS (~0U)
+#define VK_WHOLE_SIZE             (~0ULL)
+#define VK_ATTACHMENT_UNUSED      (~0U)
+define VK_QUEUE_FAMILY_IGNORED    (~0U)
+define VK_SUBPASS_EXTERNAL        (~0U)
+{{range $d := $.Definitions}}
+  {{if HasPrefix $d.Name "VK_"}}#define {{$d.Name}}  {{$d.Expression}}{{end}}
+{{end}}

+{{range $i, $p := $.Pseudonyms}}
+  {{if GetAnnotation $p "dispatchHandle"}}VK_DEFINE_HANDLE({{$p.Name}})
+  {{else if GetAnnotation $p "nonDispatchHandle"}}VK_DEFINE_NONDISP_HANDLE({{$p.Name}})
+  {{end}}
+{{end}}

+// ------------------------------------------------------------------------------------------------
+// Enumerations

+  {{range $e := $.Enums}}
+    {{if not $e.IsBitfield}}
+      {{Macro "Enum" $e}}
+    {{end}}
+  {{end}}

+// ------------------------------------------------------------------------------------------------
+// Flags

+  {{range $e := $.Enums}}
+    {{if $e.IsBitfield}}
+      {{Macro "Bitfield" $e}}
+    {{end}}
+  {{end}}

+// ------------------------------------------------------------------------------------------------
+// Vulkan structures

+  {{/* Function pointers */}}
+  {{range $f := AllCommands $}}
+    {{if GetAnnotation $f "pfn"}}
+      {{Macro "FunctionTypedef" $f}}
+    {{end}}
+  {{end}}

+  {{range $c := $.Classes}}
+    {{if not (GetAnnotation $c "internal")}}
+      {{Macro "Struct" $c}}
+    {{end}}
+  {{end}}

+// ------------------------------------------------------------------------------------------------
+// API functions

+  {{range $f := AllCommands $}}
+    {{if not (GetAnnotation $f "pfn")}}
+      {{Macro "FunctionTypedef" $f}}
+    {{end}}
+  {{end}}

+#ifdef VK_NO_PROTOTYPES

+  {{range $f := AllCommands $}}
+    {{if not (GetAnnotation $f "pfn")}}
+      {{Macro "FunctionDecl" $f}}
+    {{end}}
+  {{end}}

+#endif

+#ifdef __cplusplus
+}
+#endif

+#endif
+{{end}}
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified bitfield.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Bitfield"}}
+  {{AssertType $ "Enum"}}
+
+  {{Macro "Docs" $.Docs}}
+  typedef VkFlags {{Macro "EnumName" $}};
+  {{if $.Entries}}
+  typedef enum {
+  {{range $b := $.Entries}}
+    {{Macro "BitfieldEntryName" $b}} = {{printf "0x%.8X" $b.Value}}, {{Macro "Docs" $b.Docs}}
+  {{end}}
+  } {{Macro "EnumName" $ | TrimRight "s"}}Bits;
+  {{end}}
+  ¶
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified enum.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Enum"}}
+  {{AssertType $ "Enum"}}
+
+  {{Macro "Docs" $.Docs}}
+  typedef enum {
+    {{range $i, $e := $.Entries}}
+      {{Macro "EnumEntry" $e}} = {{printf "0x%.8X" $e.Value}}, {{Macro "Docs" $e.Docs}}
+    {{end}}
+  ¶
+    {{$name  := Macro "EnumName" $ | TrimRight "ABCDEFGHIJKLMNOQRSTUVWXYZ" | SplitPascalCase | Upper | JoinWith "_"}}
+    {{if GetAnnotation $ "enumMaxOnly"}}
+      VK_MAX_ENUM({{$name | SplitOn "VK_"}})
+    {{else}}
+      {{$first := Macro "EnumFirstEntry" $ | SplitOn $name | TrimLeft "_"}}
+      {{$last  := Macro "EnumLastEntry" $  | SplitOn $name | TrimLeft "_"}}
+      VK_ENUM_RANGE({{$name | SplitOn "VK_"}}, {{$first}}, {{$last}})
+    {{end}}
+  } {{Macro "EnumName" $}};
+  ¶
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified class.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Struct"}}
+  {{AssertType $ "Class"}}
+
+  {{Macro "Docs" $.Docs}}
+  typedef {{Macro "StructType" $}} {
+    {{ForEach $.Fields "Field" | JoinWith "\n"}}
+  } {{Macro "StructName" $}};
+  ¶
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C declaration for the specified class field.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Field"}}
+  {{AssertType $ "Field"}}
+
+  {{Node "Type" $}} {{$.Name}}§
+  {{Macro "ArrayPostfix" (TypeOf $)}}; {{Macro "Docs" $.Docs}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits either 'struct' or 'union' for the specified class.
+-------------------------------------------------------------------------------
+*/}}
+{{define "StructType"}}
+  {{AssertType $ "Class"}}
+
+  {{if GetAnnotation $ "union"}}union{{else}}struct{{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C function pointer typedef declaration for the specified command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "FunctionTypedef"}}
+  {{AssertType $ "Function"}}
+
+  typedef {{Node "Type" $.Return}} (VKAPI* {{Macro "FunctionPtrName" $}})({{Macro "Parameters" $}});
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits the C function declaration for the specified command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "FunctionDecl"}}
+  {{AssertType $ "Function"}}
+
+  {{if not (GetAnnotation $ "fptr")}}
+    {{Macro "Docs" $.Docs}}
+    {{Node "Type" $.Return}} VKAPI {{Macro "FunctionName" $}}({{Macro "Parameters" $}});
+  {{end}}
+{{end}}
diff --git a/vulkan/api/vulkan.api b/vulkan/api/vulkan.api
new file mode 100644
index 0000000..ae690a3
--- /dev/null
+++ b/vulkan/api/vulkan.api
@@ -0,0 +1,5533 @@
+// Copyright (c) 2015 The Khronos Group Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and/or associated documentation files (the
+// "Materials"), to deal in the Materials without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Materials, and to
+// permit persons to whom the Materials are 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 Materials.
+//
+// THE MATERIALS ARE 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
+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+import platform "platform.api"
+
+///////////////
+// Constants //
+///////////////
+
+// API version (major.minor.patch)
+define VERSION_MAJOR 1
+define VERSION_MINOR 0
+define VERSION_PATCH 3
+
+// API limits
+define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE 256
+define VK_UUID_SIZE                     16
+define VK_MAX_EXTENSION_NAME_SIZE       256
+define VK_MAX_DESCRIPTION_SIZE          256
+define VK_MAX_MEMORY_TYPES              32
+define VK_MAX_MEMORY_HEAPS              16    /// The maximum number of unique memory heaps, each of which supporting 1 or more memory types.
+
+// API keywords
+define VK_TRUE        1
+define VK_FALSE       0
+
+// API keyword, but needs special handling by some templates
+define NULL_HANDLE 0
+
+@extension("VK_KHR_surface") define VK_KHR_SURFACE_SPEC_VERSION                 25
+@extension("VK_KHR_surface") define VK_KHR_SURFACE_EXTENSION_NAME               "VK_KHR_surface"
+
+@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_SPEC_VERSION             67
+@extension("VK_KHR_swapchain") define VK_KHR_SWAPCHAIN_EXTENSION_NAME           "VK_KHR_swapchain"
+
+@extension("VK_KHR_display") define VK_KHR_DISPLAY_SPEC_VERSION                 21
+@extension("VK_KHR_display") define VK_KHR_DISPLAY_EXTENSION_NAME               "VK_KHR_display"
+
+@extension("VK_KHR_display_swapchain") define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION     9
+@extension("VK_KHR_display_swapchain") define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME   "VK_KHR_display_swapchain"
+
+@extension("VK_KHR_xlib_surface") define VK_KHR_XLIB_SURFACE_SPEC_VERSION       6
+@extension("VK_KHR_xlib_surface") define VK_KHR_XLIB_SURFACE_NAME               "VK_KHR_xlib_surface"
+
+@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_SPEC_VERSION         6
+@extension("VK_KHR_xcb_surface") define VK_KHR_XCB_SURFACE_NAME                 "VK_KHR_xcb_surface"
+
+@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 5
+@extension("VK_KHR_wayland_surface") define VK_KHR_WAYLAND_SURFACE_NAME         "VK_KHR_wayland_surface"
+
+@extension("VK_KHR_mir_surface") define VK_KHR_MIR_SURFACE_SPEC_VERSION         4
+@extension("VK_KHR_mir_surface") define VK_KHR_MIR_SURFACE_NAME                 "VK_KHR_mir_surface"
+
+@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
+@extension("VK_KHR_android_surface") define VK_KHR_ANDROID_SURFACE_NAME         "VK_KHR_android_surface"
+
+@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_SPEC_VERSION     5
+@extension("VK_KHR_win32_surface") define VK_KHR_WIN32_SURFACE_NAME             "VK_KHR_win32_surface"
+
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     5
+@extension("VK_ANDROID_native_buffer") define VK_ANDROID_NATIVE_BUFFER_NAME             "VK_ANDROID_native_buffer"
+
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_SPEC_VERSION       1
+@extension("VK_EXT_debug_report") define VK_EXT_DEBUG_REPORT_NAME               "VK_EXT_debug_report"
+
+
+/////////////
+//  Types  //
+/////////////
+
+type u32 VkBool32
+type u32 VkFlags
+type u64 VkDeviceSize
+type u32 VkSampleMask
+
+/// Dispatchable handle types.
+@dispatchHandle type u64 VkInstance
+@dispatchHandle type u64 VkPhysicalDevice
+@dispatchHandle type u64 VkDevice
+@dispatchHandle type u64 VkQueue
+@dispatchHandle type u64 VkCommandBuffer
+
+/// Non dispatchable handle types.
+@nonDispatchHandle type u64 VkDeviceMemory
+@nonDispatchHandle type u64 VkCommandPool
+@nonDispatchHandle type u64 VkBuffer
+@nonDispatchHandle type u64 VkBufferView
+@nonDispatchHandle type u64 VkImage
+@nonDispatchHandle type u64 VkImageView
+@nonDispatchHandle type u64 VkShaderModule
+@nonDispatchHandle type u64 VkPipeline
+@nonDispatchHandle type u64 VkPipelineLayout
+@nonDispatchHandle type u64 VkSampler
+@nonDispatchHandle type u64 VkDescriptorSet
+@nonDispatchHandle type u64 VkDescriptorSetLayout
+@nonDispatchHandle type u64 VkDescriptorPool
+@nonDispatchHandle type u64 VkFence
+@nonDispatchHandle type u64 VkSemaphore
+@nonDispatchHandle type u64 VkEvent
+@nonDispatchHandle type u64 VkQueryPool
+@nonDispatchHandle type u64 VkFramebuffer
+@nonDispatchHandle type u64 VkRenderPass
+@nonDispatchHandle type u64 VkPipelineCache
+
+@extension("VK_KHR_surface")    @nonDispatchHandle type u64 VkSurfaceKHR
+
+@extension("VK_KHR_swapchain")  @nonDispatchHandle type u64 VkSwapchainKHR
+
+@extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayKHR
+@extension("VK_KHR_display")    @nonDispatchHandle type u64 VkDisplayModeKHR
+
+@extension("VK_EXT_debug_report") @nonDispatchHandle type u64 VkDebugReportCallbackEXT
+
+
+/////////////
+//  Enums  //
+/////////////
+
+enum VkImageLayout {
+    VK_IMAGE_LAYOUT_UNDEFINED                               = 0x00000000,   /// Implicit layout an image is when its contents are undefined due to various reasons (e.g. right after creation)
+    VK_IMAGE_LAYOUT_GENERAL                                 = 0x00000001,   /// General layout when image can be used for any kind of access
+    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                = 0x00000002,   /// Optimal layout when image is only used for color attachment read/write
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL        = 0x00000003,   /// Optimal layout when image is only used for depth/stencil attachment read/write
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL         = 0x00000004,   /// Optimal layout when image is used for read only depth/stencil attachment and shader access
+    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL                = 0x00000005,   /// Optimal layout when image is used for read only shader access
+    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL                    = 0x00000006,   /// Optimal layout when image is used only as source of transfer operations
+    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL                    = 0x00000007,   /// Optimal layout when image is used only as destination of transfer operations
+    VK_IMAGE_LAYOUT_PREINITIALIZED                          = 0x00000008,   /// Initial layout used when the data is populated by the CPU
+
+    //@extension("VK_KHR_swapchain")
+    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR                         = 1000001002,
+}
+
+enum VkAttachmentLoadOp {
+    VK_ATTACHMENT_LOAD_OP_LOAD                              = 0x00000000,
+    VK_ATTACHMENT_LOAD_OP_CLEAR                             = 0x00000001,
+    VK_ATTACHMENT_LOAD_OP_DONT_CARE                         = 0x00000002,
+}
+
+enum VkAttachmentStoreOp {
+    VK_ATTACHMENT_STORE_OP_STORE                            = 0x00000000,
+    VK_ATTACHMENT_STORE_OP_DONT_CARE                        = 0x00000001,
+}
+
+enum VkImageType {
+    VK_IMAGE_TYPE_1D                                        = 0x00000000,
+    VK_IMAGE_TYPE_2D                                        = 0x00000001,
+    VK_IMAGE_TYPE_3D                                        = 0x00000002,
+}
+
+enum VkImageTiling {
+    VK_IMAGE_TILING_OPTIMAL                                 = 0x00000000,
+    VK_IMAGE_TILING_LINEAR                                  = 0x00000001,
+}
+
+enum VkImageViewType {
+    VK_IMAGE_VIEW_TYPE_1D                                   = 0x00000000,
+    VK_IMAGE_VIEW_TYPE_2D                                   = 0x00000001,
+    VK_IMAGE_VIEW_TYPE_3D                                   = 0x00000002,
+    VK_IMAGE_VIEW_TYPE_CUBE                                 = 0x00000003,
+    VK_IMAGE_VIEW_TYPE_1D_ARRAY                             = 0x00000004,
+    VK_IMAGE_VIEW_TYPE_2D_ARRAY                             = 0x00000005,
+    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY                           = 0x00000006,
+}
+
+enum VkCommandBufferLevel {
+    VK_COMMAND_BUFFER_LEVEL_PRIMARY                         = 0x00000000,
+    VK_COMMAND_BUFFER_LEVEL_SECONDARY                       = 0x00000001,
+}
+
+enum VkComponentSwizzle {
+    VK_COMPONENT_SWIZZLE_IDENTITY                           = 0x00000000,
+    VK_COMPONENT_SWIZZLE_ZERO                               = 0x00000001,
+    VK_COMPONENT_SWIZZLE_ONE                                = 0x00000002,
+    VK_COMPONENT_SWIZZLE_R                                  = 0x00000003,
+    VK_COMPONENT_SWIZZLE_G                                  = 0x00000004,
+    VK_COMPONENT_SWIZZLE_B                                  = 0x00000005,
+    VK_COMPONENT_SWIZZLE_A                                  = 0x00000006,
+}
+
+enum VkDescriptorType {
+    VK_DESCRIPTOR_TYPE_SAMPLER                              = 0x00000000,
+    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER               = 0x00000001,
+    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE                        = 0x00000002,
+    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE                        = 0x00000003,
+    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER                 = 0x00000004,
+    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER                 = 0x00000005,
+    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER                       = 0x00000006,
+    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER                       = 0x00000007,
+    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC               = 0x00000008,
+    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC               = 0x00000009,
+    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT                     = 0x0000000a,
+}
+
+enum VkQueryType {
+    VK_QUERY_TYPE_OCCLUSION                                 = 0x00000000,
+    VK_QUERY_TYPE_PIPELINE_STATISTICS                       = 0x00000001, /// Optional
+    VK_QUERY_TYPE_TIMESTAMP                                 = 0x00000002,
+}
+
+enum VkBorderColor {
+    VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK                 = 0x00000000,
+    VK_BORDER_COLOR_INT_TRANSPARENT_BLACK                   = 0x00000001,
+    VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK                      = 0x00000002,
+    VK_BORDER_COLOR_INT_OPAQUE_BLACK                        = 0x00000003,
+    VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE                      = 0x00000004,
+    VK_BORDER_COLOR_INT_OPAQUE_WHITE                        = 0x00000005,
+}
+
+enum VkPipelineBindPoint {
+    VK_PIPELINE_BIND_POINT_GRAPHICS                         = 0x00000000,
+    VK_PIPELINE_BIND_POINT_COMPUTE                          = 0x00000001,
+}
+
+enum VkPrimitiveTopology {
+    VK_PRIMITIVE_TOPOLOGY_POINT_LIST                        = 0x00000000,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST                         = 0x00000001,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP                        = 0x00000002,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST                     = 0x00000003,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP                    = 0x00000004,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN                      = 0x00000005,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY          = 0x00000006,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY         = 0x00000007,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY      = 0x00000008,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY     = 0x00000009,
+    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST                        = 0x0000000a,
+}
+
+enum VkSharingMode {
+    VK_SHARING_MODE_EXCLUSIVE                               = 0x00000000,
+    VK_SHARING_MODE_CONCURRENT                              = 0x00000001,
+}
+
+enum VkIndexType {
+    VK_INDEX_TYPE_UINT16                                    = 0x00000000,
+    VK_INDEX_TYPE_UINT32                                    = 0x00000001,
+}
+
+enum VkFilter {
+    VK_FILTER_NEAREST                                       = 0x00000000,
+    VK_FILTER_LINEAR                                        = 0x00000001,
+}
+
+enum VkSamplerMipmapMode {
+    VK_SAMPLER_MIPMAP_MODE_NEAREST                          = 0x00000001,   /// Choose nearest mip level
+    VK_SAMPLER_MIPMAP_MODE_LINEAR                           = 0x00000002,   /// Linear filter between mip levels
+}
+
+enum VkSamplerAddressMode {
+    VK_SAMPLER_ADDRESS_MODE_REPEAT                          = 0x00000000,
+    VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT                 = 0x00000001,
+    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE                   = 0x00000002,
+    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER                 = 0x00000003,
+    VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE            = 0x00000004,
+}
+
+enum VkCompareOp {
+    VK_COMPARE_OP_NEVER                                     = 0x00000000,
+    VK_COMPARE_OP_LESS                                      = 0x00000001,
+    VK_COMPARE_OP_EQUAL                                     = 0x00000002,
+    VK_COMPARE_OP_LESS_OR_EQUAL                             = 0x00000003,
+    VK_COMPARE_OP_GREATER                                   = 0x00000004,
+    VK_COMPARE_OP_NOT_EQUAL                                 = 0x00000005,
+    VK_COMPARE_OP_GREATER_OR_EQUAL                          = 0x00000006,
+    VK_COMPARE_OP_ALWAYS                                    = 0x00000007,
+}
+
+enum VkPolygonMode {
+    VK_POLYGON_MODE_FILL                                    = 0x00000000,
+    VK_POLYGON_MODE_LINE                                    = 0x00000001,
+    VK_POLYGON_MODE_POINT                                   = 0x00000002,
+}
+
+enum VkFrontFace {
+    VK_FRONT_FACE_COUNTER_CLOCKWISE                         = 0x00000000,
+    VK_FRONT_FACE_CLOCKWISE                                 = 0x00000001,
+}
+
+enum VkBlendFactor {
+    VK_BLEND_FACTOR_ZERO                                    = 0x00000000,
+    VK_BLEND_FACTOR_ONE                                     = 0x00000001,
+    VK_BLEND_FACTOR_SRC_COLOR                               = 0x00000002,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR                     = 0x00000003,
+    VK_BLEND_FACTOR_DST_COLOR                               = 0x00000004,
+    VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR                     = 0x00000005,
+    VK_BLEND_FACTOR_SRC_ALPHA                               = 0x00000006,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA                     = 0x00000007,
+    VK_BLEND_FACTOR_DST_ALPHA                               = 0x00000008,
+    VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA                     = 0x00000009,
+    VK_BLEND_FACTOR_CONSTANT_COLOR                          = 0x0000000a,
+    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR                = 0x0000000b,
+    VK_BLEND_FACTOR_CONSTANT_ALPHA                          = 0x0000000c,
+    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA                = 0x0000000d,
+    VK_BLEND_FACTOR_SRC_ALPHA_SATURATE                      = 0x0000000e,
+    VK_BLEND_FACTOR_SRC1_COLOR                              = 0x0000000f,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR                    = 0x00000010,
+    VK_BLEND_FACTOR_SRC1_ALPHA                              = 0x00000011,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA                    = 0x00000012,
+}
+
+enum VkBlendOp {
+    VK_BLEND_OP_ADD                                         = 0x00000000,
+    VK_BLEND_OP_SUBTRACT                                    = 0x00000001,
+    VK_BLEND_OP_REVERSE_SUBTRACT                            = 0x00000002,
+    VK_BLEND_OP_MIN                                         = 0x00000003,
+    VK_BLEND_OP_MAX                                         = 0x00000004,
+}
+
+enum VkStencilOp {
+    VK_STENCIL_OP_KEEP                                      = 0x00000000,
+    VK_STENCIL_OP_ZERO                                      = 0x00000001,
+    VK_STENCIL_OP_REPLACE                                   = 0x00000002,
+    VK_STENCIL_OP_INCREMENT_AND_CLAMP                       = 0x00000003,
+    VK_STENCIL_OP_DECREMENT_AND_CLAMP                       = 0x00000004,
+    VK_STENCIL_OP_INVERT                                    = 0x00000005,
+    VK_STENCIL_OP_INCREMENT_AND_WRAP                        = 0x00000006,
+    VK_STENCIL_OP_DECREMENT_AND_WRAP                        = 0x00000007,
+}
+
+enum VkLogicOp {
+    VK_LOGIC_OP_CLEAR                                       = 0x00000000,
+    VK_LOGIC_OP_AND                                         = 0x00000001,
+    VK_LOGIC_OP_AND_REVERSE                                 = 0x00000002,
+    VK_LOGIC_OP_COPY                                        = 0x00000003,
+    VK_LOGIC_OP_AND_INVERTED                                = 0x00000004,
+    VK_LOGIC_OP_NO_OP                                       = 0x00000005,
+    VK_LOGIC_OP_XOR                                         = 0x00000006,
+    VK_LOGIC_OP_OR                                          = 0x00000007,
+    VK_LOGIC_OP_NOR                                         = 0x00000008,
+    VK_LOGIC_OP_EQUIVALENT                                  = 0x00000009,
+    VK_LOGIC_OP_INVERT                                      = 0x0000000a,
+    VK_LOGIC_OP_OR_REVERSE                                  = 0x0000000b,
+    VK_LOGIC_OP_COPY_INVERTED                               = 0x0000000c,
+    VK_LOGIC_OP_OR_INVERTED                                 = 0x0000000d,
+    VK_LOGIC_OP_NAND                                        = 0x0000000e,
+    VK_LOGIC_OP_SET                                         = 0x0000000f,
+}
+
+enum VkSystemAllocationScope {
+    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND                      = 0x00000000,
+    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT                       = 0x00000001,
+    VK_SYSTEM_ALLOCATION_SCOPE_CACHE                        = 0x00000002,
+    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE                       = 0x00000003,
+    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE                     = 0x00000004,
+}
+
+enum VkInternalAllocationType {
+    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE                  = 0x00000000,
+}
+
+enum VkPhysicalDeviceType {
+    VK_PHYSICAL_DEVICE_TYPE_OTHER                           = 0x00000000,
+    VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU                  = 0x00000001,
+    VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU                    = 0x00000002,
+    VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU                     = 0x00000003,
+    VK_PHYSICAL_DEVICE_TYPE_CPU                             = 0x00000004,
+}
+
+enum VkVertexInputRate {
+    VK_VERTEX_INPUT_RATE_VERTEX                             = 0x00000000,
+    VK_VERTEX_INPUT_RATE_INSTANCE                           = 0x00000001,
+}
+
+/// Vulkan format definitions
+enum VkFormat {
+    VK_FORMAT_UNDEFINED                                     = 0,
+    VK_FORMAT_R4G4_UNORM_PACK8                              = 1,
+    VK_FORMAT_R4G4B4A4_UNORM_PACK16                         = 2,
+    VK_FORMAT_B4G4R4A4_UNORM_PACK16                         = 3,
+    VK_FORMAT_R5G6B5_UNORM_PACK16                           = 4,
+    VK_FORMAT_B5G6R5_UNORM_PACK16                           = 5,
+    VK_FORMAT_R5G5B5A1_UNORM_PACK16                         = 6,
+    VK_FORMAT_B5G5R5A1_UNORM_PACK16                         = 7,
+    VK_FORMAT_A1R5G5B5_UNORM_PACK16                         = 8,
+    VK_FORMAT_R8_UNORM                                      = 9,
+    VK_FORMAT_R8_SNORM                                      = 10,
+    VK_FORMAT_R8_USCALED                                    = 11,
+    VK_FORMAT_R8_SSCALED                                    = 12,
+    VK_FORMAT_R8_UINT                                       = 13,
+    VK_FORMAT_R8_SINT                                       = 14,
+    VK_FORMAT_R8_SRGB                                       = 15,
+    VK_FORMAT_R8G8_UNORM                                    = 16,
+    VK_FORMAT_R8G8_SNORM                                    = 17,
+    VK_FORMAT_R8G8_USCALED                                  = 18,
+    VK_FORMAT_R8G8_SSCALED                                  = 19,
+    VK_FORMAT_R8G8_UINT                                     = 20,
+    VK_FORMAT_R8G8_SINT                                     = 21,
+    VK_FORMAT_R8G8_SRGB                                     = 22,
+    VK_FORMAT_R8G8B8_UNORM                                  = 23,
+    VK_FORMAT_R8G8B8_SNORM                                  = 24,
+    VK_FORMAT_R8G8B8_USCALED                                = 25,
+    VK_FORMAT_R8G8B8_SSCALED                                = 26,
+    VK_FORMAT_R8G8B8_UINT                                   = 27,
+    VK_FORMAT_R8G8B8_SINT                                   = 28,
+    VK_FORMAT_R8G8B8_SRGB                                   = 29,
+    VK_FORMAT_B8G8R8_UNORM                                  = 30,
+    VK_FORMAT_B8G8R8_SNORM                                  = 31,
+    VK_FORMAT_B8G8R8_USCALED                                = 32,
+    VK_FORMAT_B8G8R8_SSCALED                                = 33,
+    VK_FORMAT_B8G8R8_UINT                                   = 34,
+    VK_FORMAT_B8G8R8_SINT                                   = 35,
+    VK_FORMAT_B8G8R8_SRGB                                   = 36,
+    VK_FORMAT_R8G8B8A8_UNORM                                = 37,
+    VK_FORMAT_R8G8B8A8_SNORM                                = 38,
+    VK_FORMAT_R8G8B8A8_USCALED                              = 39,
+    VK_FORMAT_R8G8B8A8_SSCALED                              = 40,
+    VK_FORMAT_R8G8B8A8_UINT                                 = 41,
+    VK_FORMAT_R8G8B8A8_SINT                                 = 42,
+    VK_FORMAT_R8G8B8A8_SRGB                                 = 43,
+    VK_FORMAT_B8G8R8A8_UNORM                                = 44,
+    VK_FORMAT_B8G8R8A8_SNORM                                = 45,
+    VK_FORMAT_B8G8R8A8_USCALED                              = 46,
+    VK_FORMAT_B8G8R8A8_SSCALED                              = 47,
+    VK_FORMAT_B8G8R8A8_UINT                                 = 48,
+    VK_FORMAT_B8G8R8A8_SINT                                 = 49,
+    VK_FORMAT_B8G8R8A8_SRGB                                 = 50,
+    VK_FORMAT_A8B8G8R8_UNORM_PACK32                         = 51,
+    VK_FORMAT_A8B8G8R8_SNORM_PACK32                         = 52,
+    VK_FORMAT_A8B8G8R8_USCALED_PACK32                       = 53,
+    VK_FORMAT_A8B8G8R8_SSCALED_PACK32                       = 54,
+    VK_FORMAT_A8B8G8R8_UINT_PACK32                          = 55,
+    VK_FORMAT_A8B8G8R8_SINT_PACK32                          = 56,
+    VK_FORMAT_A8B8G8R8_SRGB_PACK32                          = 57,
+    VK_FORMAT_A2R10G10B10_UNORM_PACK32                      = 58,
+    VK_FORMAT_A2R10G10B10_SNORM_PACK32                      = 59,
+    VK_FORMAT_A2R10G10B10_USCALED_PACK32                    = 60,
+    VK_FORMAT_A2R10G10B10_SSCALED_PACK32                    = 61,
+    VK_FORMAT_A2R10G10B10_UINT_PACK32                       = 62,
+    VK_FORMAT_A2R10G10B10_SINT_PACK32                       = 63,
+    VK_FORMAT_A2B10G10R10_UNORM_PACK32                      = 64,
+    VK_FORMAT_A2B10G10R10_SNORM_PACK32                      = 65,
+    VK_FORMAT_A2B10G10R10_USCALED_PACK32                    = 66,
+    VK_FORMAT_A2B10G10R10_SSCALED_PACK32                    = 67,
+    VK_FORMAT_A2B10G10R10_UINT_PACK32                       = 68,
+    VK_FORMAT_A2B10G10R10_SINT_PACK32                       = 69,
+    VK_FORMAT_R16_UNORM                                     = 70,
+    VK_FORMAT_R16_SNORM                                     = 71,
+    VK_FORMAT_R16_USCALED                                   = 72,
+    VK_FORMAT_R16_SSCALED                                   = 73,
+    VK_FORMAT_R16_UINT                                      = 74,
+    VK_FORMAT_R16_SINT                                      = 75,
+    VK_FORMAT_R16_SFLOAT                                    = 76,
+    VK_FORMAT_R16G16_UNORM                                  = 77,
+    VK_FORMAT_R16G16_SNORM                                  = 78,
+    VK_FORMAT_R16G16_USCALED                                = 79,
+    VK_FORMAT_R16G16_SSCALED                                = 80,
+    VK_FORMAT_R16G16_UINT                                   = 81,
+    VK_FORMAT_R16G16_SINT                                   = 82,
+    VK_FORMAT_R16G16_SFLOAT                                 = 83,
+    VK_FORMAT_R16G16B16_UNORM                               = 84,
+    VK_FORMAT_R16G16B16_SNORM                               = 85,
+    VK_FORMAT_R16G16B16_USCALED                             = 86,
+    VK_FORMAT_R16G16B16_SSCALED                             = 87,
+    VK_FORMAT_R16G16B16_UINT                                = 88,
+    VK_FORMAT_R16G16B16_SINT                                = 89,
+    VK_FORMAT_R16G16B16_SFLOAT                              = 90,
+    VK_FORMAT_R16G16B16A16_UNORM                            = 91,
+    VK_FORMAT_R16G16B16A16_SNORM                            = 92,
+    VK_FORMAT_R16G16B16A16_USCALED                          = 93,
+    VK_FORMAT_R16G16B16A16_SSCALED                          = 94,
+    VK_FORMAT_R16G16B16A16_UINT                             = 95,
+    VK_FORMAT_R16G16B16A16_SINT                             = 96,
+    VK_FORMAT_R16G16B16A16_SFLOAT                           = 97,
+    VK_FORMAT_R32_UINT                                      = 98,
+    VK_FORMAT_R32_SINT                                      = 99,
+    VK_FORMAT_R32_SFLOAT                                    = 100,
+    VK_FORMAT_R32G32_UINT                                   = 101,
+    VK_FORMAT_R32G32_SINT                                   = 102,
+    VK_FORMAT_R32G32_SFLOAT                                 = 103,
+    VK_FORMAT_R32G32B32_UINT                                = 104,
+    VK_FORMAT_R32G32B32_SINT                                = 105,
+    VK_FORMAT_R32G32B32_SFLOAT                              = 106,
+    VK_FORMAT_R32G32B32A32_UINT                             = 107,
+    VK_FORMAT_R32G32B32A32_SINT                             = 108,
+    VK_FORMAT_R32G32B32A32_SFLOAT                           = 109,
+    VK_FORMAT_R64_UINT                                      = 110,
+    VK_FORMAT_R64_SINT                                      = 111,
+    VK_FORMAT_R64_SFLOAT                                    = 112,
+    VK_FORMAT_R64G64_UINT                                   = 113,
+    VK_FORMAT_R64G64_SINT                                   = 114,
+    VK_FORMAT_R64G64_SFLOAT                                 = 115,
+    VK_FORMAT_R64G64B64_UINT                                = 116,
+    VK_FORMAT_R64G64B64_SINT                                = 117,
+    VK_FORMAT_R64G64B64_SFLOAT                              = 118,
+    VK_FORMAT_R64G64B64A64_UINT                             = 119,
+    VK_FORMAT_R64G64B64A64_SINT                             = 120,
+    VK_FORMAT_R64G64B64A64_SFLOAT                           = 121,
+    VK_FORMAT_B10G11R11_UFLOAT_PACK32                       = 122,
+    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32                        = 123,
+    VK_FORMAT_D16_UNORM                                     = 124,
+    VK_FORMAT_X8_D24_UNORM_PACK32                           = 125,
+    VK_FORMAT_D32_SFLOAT                                    = 126,
+    VK_FORMAT_S8_UINT                                       = 127,
+    VK_FORMAT_D16_UNORM_S8_UINT                             = 128,
+    VK_FORMAT_D24_UNORM_S8_UINT                             = 129,
+    VK_FORMAT_D32_SFLOAT_S8_UINT                            = 130,
+    VK_FORMAT_BC1_RGB_UNORM_BLOCK                           = 131,
+    VK_FORMAT_BC1_RGB_SRGB_BLOCK                            = 132,
+    VK_FORMAT_BC1_RGBA_UNORM_BLOCK                          = 133,
+    VK_FORMAT_BC1_RGBA_SRGB_BLOCK                           = 134,
+    VK_FORMAT_BC2_UNORM_BLOCK                               = 135,
+    VK_FORMAT_BC2_SRGB_BLOCK                                = 136,
+    VK_FORMAT_BC3_UNORM_BLOCK                               = 137,
+    VK_FORMAT_BC3_SRGB_BLOCK                                = 138,
+    VK_FORMAT_BC4_UNORM_BLOCK                               = 139,
+    VK_FORMAT_BC4_SNORM_BLOCK                               = 140,
+    VK_FORMAT_BC5_UNORM_BLOCK                               = 141,
+    VK_FORMAT_BC5_SNORM_BLOCK                               = 142,
+    VK_FORMAT_BC6H_UFLOAT_BLOCK                             = 143,
+    VK_FORMAT_BC6H_SFLOAT_BLOCK                             = 144,
+    VK_FORMAT_BC7_UNORM_BLOCK                               = 145,
+    VK_FORMAT_BC7_SRGB_BLOCK                                = 146,
+    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK                       = 147,
+    VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK                        = 148,
+    VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK                     = 149,
+    VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK                      = 150,
+    VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK                     = 151,
+    VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK                      = 152,
+    VK_FORMAT_EAC_R11_UNORM_BLOCK                           = 153,
+    VK_FORMAT_EAC_R11_SNORM_BLOCK                           = 154,
+    VK_FORMAT_EAC_R11G11_UNORM_BLOCK                        = 155,
+    VK_FORMAT_EAC_R11G11_SNORM_BLOCK                        = 156,
+    VK_FORMAT_ASTC_4x4_UNORM_BLOCK                          = 157,
+    VK_FORMAT_ASTC_4x4_SRGB_BLOCK                           = 158,
+    VK_FORMAT_ASTC_5x4_UNORM_BLOCK                          = 159,
+    VK_FORMAT_ASTC_5x4_SRGB_BLOCK                           = 160,
+    VK_FORMAT_ASTC_5x5_UNORM_BLOCK                          = 161,
+    VK_FORMAT_ASTC_5x5_SRGB_BLOCK                           = 162,
+    VK_FORMAT_ASTC_6x5_UNORM_BLOCK                          = 163,
+    VK_FORMAT_ASTC_6x5_SRGB_BLOCK                           = 164,
+    VK_FORMAT_ASTC_6x6_UNORM_BLOCK                          = 165,
+    VK_FORMAT_ASTC_6x6_SRGB_BLOCK                           = 166,
+    VK_FORMAT_ASTC_8x5_UNORM_BLOCK                          = 167,
+    VK_FORMAT_ASTC_8x5_SRGB_BLOCK                           = 168,
+    VK_FORMAT_ASTC_8x6_UNORM_BLOCK                          = 169,
+    VK_FORMAT_ASTC_8x6_SRGB_BLOCK                           = 170,
+    VK_FORMAT_ASTC_8x8_UNORM_BLOCK                          = 171,
+    VK_FORMAT_ASTC_8x8_SRGB_BLOCK                           = 172,
+    VK_FORMAT_ASTC_10x5_UNORM_BLOCK                         = 173,
+    VK_FORMAT_ASTC_10x5_SRGB_BLOCK                          = 174,
+    VK_FORMAT_ASTC_10x6_UNORM_BLOCK                         = 175,
+    VK_FORMAT_ASTC_10x6_SRGB_BLOCK                          = 176,
+    VK_FORMAT_ASTC_10x8_UNORM_BLOCK                         = 177,
+    VK_FORMAT_ASTC_10x8_SRGB_BLOCK                          = 178,
+    VK_FORMAT_ASTC_10x10_UNORM_BLOCK                        = 179,
+    VK_FORMAT_ASTC_10x10_SRGB_BLOCK                         = 180,
+    VK_FORMAT_ASTC_12x10_UNORM_BLOCK                        = 181,
+    VK_FORMAT_ASTC_12x10_SRGB_BLOCK                         = 182,
+    VK_FORMAT_ASTC_12x12_UNORM_BLOCK                        = 183,
+    VK_FORMAT_ASTC_12x12_SRGB_BLOCK                         = 184,
+}
+
+/// Structure type enumerant
+enum VkStructureType {
+    VK_STRUCTURE_TYPE_APPLICATION_INFO                          = 0,
+    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO                      = 1,
+    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO                  = 2,
+    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO                        = 3,
+    VK_STRUCTURE_TYPE_SUBMIT_INFO                               = 4,
+    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO                      = 5,
+    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE                       = 6,
+    VK_STRUCTURE_TYPE_BIND_SPARSE_INFO                          = 7,
+    VK_STRUCTURE_TYPE_FENCE_CREATE_INFO                         = 8,
+    VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO                     = 9,
+    VK_STRUCTURE_TYPE_EVENT_CREATE_INFO                         = 10,
+    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO                    = 11,
+    VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO                        = 12,
+    VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO                   = 13,
+    VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO                         = 14,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO                    = 15,
+    VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO                 = 16,
+    VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO                = 17,
+    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO         = 18,
+    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO   = 19,
+    VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
+    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO   = 21,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO       = 22,
+    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO  = 23,
+    VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO    = 24,
+    VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO  = 25,
+    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO    = 26,
+    VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO        = 27,
+    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO             = 28,
+    VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO              = 29,
+    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO               = 30,
+    VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO                       = 31,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO         = 32,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO               = 33,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO              = 34,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET                      = 35,
+    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET                       = 36,
+    VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO                   = 37,
+    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO                   = 38,
+    VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO                  = 39,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO              = 40,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO           = 41,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO                 = 42,
+    VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO                    = 43,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER                     = 44,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER                      = 45,
+    VK_STRUCTURE_TYPE_MEMORY_BARRIER                            = 46,
+    VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO               = 47,
+    VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO                 = 48,
+
+    //@extension("VK_KHR_swapchain")
+    VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR                 = 1000001000,
+    VK_STRUCTURE_TYPE_PRESENT_INFO_KHR                          = 1000001001,
+
+    //@extension("VK_KHR_display")
+    VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR              = 1000002000,
+    VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR           = 1000002001,
+
+    //@extension("VK_KHR_display_swapchain")
+    VK_STRUCTURE_TYPE_DISPLAY_DISPLAY_PRESENT_INFO_KHR          = 1000003000,
+
+    //@extension("VK_KHR_xlib_surface")
+    VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR              = 1000004000,
+
+    //@extension("VK_KHR_xcb_surface")
+    VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR               = 1000005000,
+
+    //@extension("VK_KHR_wayland_surface")
+    VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR           = 1000006000,
+
+    //@extension("VK_KHR_mir_surface")
+    VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR               = 1000007000,
+
+    //@extension("VK_KHR_android_surface")
+    VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR           = 1000008000,
+
+    //@extension("VK_KHR_win32_surface")
+    VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR             = 1000009000,
+
+    //@extension("VK_ANDROID_native_buffer")
+    VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID                     = 1000010000,
+
+    //@extension("VK_EXT_debug_report")
+    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT              = 1000011000,
+}
+
+enum VkSubpassContents {
+    VK_SUBPASS_CONTENTS_INLINE                              = 0x00000000,
+    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS           = 0x00000001,
+}
+
+enum VkPipelineCacheHeaderVersion {
+    VK_PIPELINE_CACHE_HEADER_VERSION_ONE                    = 1,
+}
+
+@lastUnused(-11)
+/// Error and return codes
+enum VkResult {
+    // Return codes for successful operation execution (positive values)
+    VK_SUCCESS                                              = 0,
+    VK_NOT_READY                                            = 1,
+    VK_TIMEOUT                                              = 2,
+    VK_EVENT_SET                                            = 3,
+    VK_EVENT_RESET                                          = 4,
+    VK_INCOMPLETE                                           = 5,
+
+    //@extension("VK_KHR_swapchain")
+    VK_SUBOPTIMAL_KHR                                       = 1000001003,
+
+    // Error codes (negative values)
+    VK_ERROR_OUT_OF_HOST_MEMORY                             = 0xFFFFFFFF, // -1
+    VK_ERROR_OUT_OF_DEVICE_MEMORY                           = 0xFFFFFFFE, // -2
+    VK_ERROR_INITIALIZATION_FAILED                          = 0xFFFFFFFD, // -3
+    VK_ERROR_DEVICE_LOST                                    = 0xFFFFFFFC, // -4
+    VK_ERROR_MEMORY_MAP_FAILED                              = 0xFFFFFFFB, // -5
+    VK_ERROR_LAYER_NOT_PRESENT                              = 0xFFFFFFFA, // -6
+    VK_ERROR_EXTENSION_NOT_PRESENT                          = 0xFFFFFFF9, // -7
+    VK_ERROR_FEATURE_NOT_PRESENT                            = 0xFFFFFFF8, // -8
+    VK_ERROR_INCOMPATIBLE_DRIVER                            = 0xFFFFFFF7, // -9
+    VK_ERROR_TOO_MANY_OBJECTS                               = 0xFFFFFFF6, // -10
+    VK_ERROR_FORMAT_NOT_SUPPORTED                           = 0xFFFFFFF5, // -11
+
+    //@extension("VK_KHR_surface")
+    VK_ERROR_SURFACE_LOST_KHR                               = 0xC4653600, // -1000000000
+
+    //@extension("VK_KHR_surface")
+    VK_ERROR_NATIVE_WINDOW_IN_USE_KHR                       = 0xC46535FF, // -1000008001
+
+    //@extension("VK_KHR_swapchain")
+    VK_ERROR_OUT_OF_DATE_KHR                                = 0xC4653214, // -1000001004
+
+    //@extension("VK_KHR_display_swapchain")
+    VK_ERROR_INCOMPATIBLE_DISPLAY_KHR                       = 0xC4652A47, // -1000003001
+
+    //@extension("VK_EXT_debug_report")
+    VK_ERROR_VALIDATION_FAILED_EXT                          = 0xC4650B07, // -1000011001
+}
+
+enum VkDynamicState {
+    VK_DYNAMIC_STATE_VIEWPORT                               = 0x00000000,
+    VK_DYNAMIC_STATE_SCISSOR                                = 0x00000001,
+    VK_DYNAMIC_STATE_LINE_WIDTH                             = 0x00000002,
+    VK_DYNAMIC_STATE_DEPTH_BIAS                             = 0x00000003,
+    VK_DYNAMIC_STATE_BLEND_CONSTANTS                        = 0x00000004,
+    VK_DYNAMIC_STATE_DEPTH_BOUNDS                           = 0x00000005,
+    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK                   = 0x00000006,
+    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK                     = 0x00000007,
+    VK_DYNAMIC_STATE_STENCIL_REFERENCE                      = 0x00000008,
+}
+
+@extension("VK_KHR_surface")
+enum VkPresentModeKHR {
+    VK_PRESENT_MODE_IMMEDIATE_KHR                           = 0x00000000,
+    VK_PRESENT_MODE_MAILBOX_KHR                             = 0x00000001,
+    VK_PRESENT_MODE_FIFO_KHR                                = 0x00000002,
+    VK_PRESENT_MODE_FIFO_RELAXED_KHR                        = 0x00000003,
+}
+
+@extension("VK_KHR_surface")
+enum VkColorSpaceKHR {
+    VK_COLORSPACE_SRGB_NONLINEAR_KHR                        = 0x00000000,
+}
+
+@extension("VK_EXT_debug_report")
+enum VkDebugReportObjectTypeEXT {
+    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT                 = 0,
+    VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT                = 1,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT         = 2,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT                  = 3,
+    VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT                   = 4,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT               = 5,
+    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT          = 6,
+    VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT                   = 7,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT           = 8,
+    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT                  = 9,
+    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT                   = 10,
+    VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT                   = 11,
+    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT              = 12,
+    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT             = 13,
+    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT              = 14,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT           = 15,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT          = 16,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT         = 17,
+    VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT             = 18,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT                = 19,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT   = 20,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT                 = 21,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT         = 22,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT          = 23,
+    VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT             = 24,
+    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT            = 25,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT             = 26,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT           = 27,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT            = 28,
+}
+
+@extension("VK_EXT_debug_report")
+enum VkDebugReportErrorEXT {
+    VK_DEBUG_REPORT_ERROR_NONE_EXT                          = 0,
+    VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT                  = 1,
+}
+
+
+/////////////////
+//  Bitfields  //
+/////////////////
+
+/// Queue capabilities
+type VkFlags VkQueueFlags
+bitfield VkQueueFlagBits {
+    VK_QUEUE_GRAPHICS_BIT                                   = 0x00000001,    /// Queue supports graphics operations
+    VK_QUEUE_COMPUTE_BIT                                    = 0x00000002,    /// Queue supports compute operations
+    VK_QUEUE_TRANSFER_BIT                                   = 0x00000004,    /// Queue supports transfer operations
+    VK_QUEUE_SPARSE_BINDING_BIT                             = 0x00000008,    /// Queue supports sparse resource memory management operations
+}
+
+/// Memory properties passed into vkAllocMemory().
+type VkFlags VkMemoryPropertyFlags
+bitfield VkMemoryPropertyFlagBits {
+    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT                     = 0x00000001,
+    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT                     = 0x00000002,
+    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT                    = 0x00000004,
+    VK_MEMORY_PROPERTY_HOST_CACHED_BIT                      = 0x00000008,
+    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT                 = 0x00000010,
+}
+
+/// Memory heap flags
+type VkFlags VkMemoryHeapFlags
+bitfield VkMemoryHeapFlagBits {
+    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT                         = 0x00000001,
+}
+
+/// Access flags
+type VkFlags VkAccessFlags
+bitfield VkAccessFlagBits {
+    VK_ACCESS_INDIRECT_COMMAND_READ_BIT                     = 0x00000001,
+    VK_ACCESS_INDEX_READ_BIT                                = 0x00000002,
+    VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT                     = 0x00000004,
+    VK_ACCESS_UNIFORM_READ_BIT                              = 0x00000008,
+    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT                     = 0x00000010,
+    VK_ACCESS_SHADER_READ_BIT                               = 0x00000020,
+    VK_ACCESS_SHADER_WRITE_BIT                              = 0x00000040,
+    VK_ACCESS_COLOR_ATTACHMENT_READ_BIT                     = 0x00000080,
+    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT                    = 0x00000100,
+    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT             = 0x00000200,
+    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT            = 0x00000400,
+    VK_ACCESS_TRANSFER_READ_BIT                             = 0x00000800,
+    VK_ACCESS_TRANSFER_WRITE_BIT                            = 0x00001000,
+    VK_ACCESS_HOST_READ_BIT                                 = 0x00002000,
+    VK_ACCESS_HOST_WRITE_BIT                                = 0x00004000,
+    VK_ACCESS_MEMORY_READ_BIT                               = 0x00008000,
+    VK_ACCESS_MEMORY_WRITE_BIT                              = 0x00010000,
+}
+
+/// Buffer usage flags
+type VkFlags VkBufferUsageFlags
+bitfield VkBufferUsageFlagBits {
+    VK_BUFFER_USAGE_TRANSFER_SRC_BIT                        = 0x00000001,    /// Can be used as a source of transfer operations
+    VK_BUFFER_USAGE_TRANSFER_DST_BIT                        = 0x00000002,    /// Can be used as a destination of transfer operations
+    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT                = 0x00000004,    /// Can be used as TBO
+    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT                = 0x00000008,    /// Can be used as IBO
+    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT                      = 0x00000010,    /// Can be used as UBO
+    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT                      = 0x00000020,    /// Can be used as SSBO
+    VK_BUFFER_USAGE_INDEX_BUFFER_BIT                        = 0x00000040,    /// Can be used as source of fixed function index fetch (index buffer)
+    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT                       = 0x00000080,    /// Can be used as source of fixed function vertex fetch (VBO)
+    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT                     = 0x00000100,    /// Can be the source of indirect parameters (e.g. indirect buffer, parameter buffer)
+}
+
+/// Buffer creation flags
+type VkFlags VkBufferCreateFlags
+bitfield VkBufferCreateFlagBits {
+    VK_BUFFER_CREATE_SPARSE_BINDING_BIT                     = 0x00000001,    /// Buffer should support sparse backing
+    VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT                   = 0x00000002,    /// Buffer should support sparse backing with partial residency
+    VK_BUFFER_CREATE_SPARSE_ALIASED_BIT                     = 0x00000004,    /// Buffer should support constent data access to physical memory blocks mapped into multiple locations of sparse buffers
+}
+
+/// Shader stage flags
+type VkFlags VkShaderStageFlags
+bitfield VkShaderStageFlagBits {
+    VK_SHADER_STAGE_VERTEX_BIT                              = 0x00000001,
+    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT                = 0x00000002,
+    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT             = 0x00000004,
+    VK_SHADER_STAGE_GEOMETRY_BIT                            = 0x00000008,
+    VK_SHADER_STAGE_FRAGMENT_BIT                            = 0x00000010,
+    VK_SHADER_STAGE_COMPUTE_BIT                             = 0x00000020,
+    VK_SHADER_STAGE_ALL_GRAPHICS                            = 0x0000001F,
+
+    VK_SHADER_STAGE_ALL                                     = 0x7FFFFFFF,
+}
+
+/// Descriptor pool create flags
+type VkFlags VkDescriptorPoolCreateFlags
+bitfield VkDescriptorPoolCreateFlagBits {
+    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT       = 0x00000001,
+}
+
+/// Descriptor pool reset flags
+type VkFlags VkDescriptorPoolResetFlags
+//bitfield VkDescriptorPoolResetFlagBits {
+//}
+
+/// Image usage flags
+type VkFlags VkImageUsageFlags
+bitfield VkImageUsageFlagBits {
+    VK_IMAGE_USAGE_TRANSFER_SRC_BIT                         = 0x00000001,    /// Can be used as a source of transfer operations
+    VK_IMAGE_USAGE_TRANSFER_DST_BIT                         = 0x00000002,    /// Can be used as a destination of transfer operations
+    VK_IMAGE_USAGE_SAMPLED_BIT                              = 0x00000004,    /// Can be sampled from (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
+    VK_IMAGE_USAGE_STORAGE_BIT                              = 0x00000008,    /// Can be used as storage image (STORAGE_IMAGE descriptor type)
+    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT                     = 0x00000010,    /// Can be used as framebuffer color attachment
+    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT             = 0x00000020,    /// Can be used as framebuffer depth/stencil attachment
+    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT                 = 0x00000040,    /// Image data not needed outside of rendering
+    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT                     = 0x00000080,    /// Can be used as framebuffer input attachment
+}
+
+/// Image creation flags
+type VkFlags VkImageCreateFlags
+bitfield VkImageCreateFlagBits {
+    VK_IMAGE_CREATE_SPARSE_BINDING_BIT                      = 0x00000001,    /// Image should support sparse backing
+    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT                    = 0x00000002,    /// Image should support sparse backing with partial residency
+    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT                      = 0x00000004,    /// Image should support constent data access to physical memory blocks mapped into multiple locations of sparse images
+    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT                      = 0x00000008,    /// Allows image views to have different format than the base image
+    VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT                     = 0x00000010,    /// Allows creating image views with cube type from the created image
+}
+
+/// Image view creation flags
+type VkFlags VkImageViewCreateFlags
+//bitfield VkImageViewCreateFlagBits {
+//}
+
+/// Pipeline creation flags
+type VkFlags VkPipelineCreateFlags
+bitfield VkPipelineCreateFlagBits {
+    VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT             = 0x00000001,
+    VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT                = 0x00000002,
+    VK_PIPELINE_CREATE_DERIVATIVE_BIT                       = 0x00000004,
+}
+
+/// Color component flags
+type VkFlags VkColorComponentFlags
+bitfield VkColorComponentFlagBits {
+    VK_COLOR_COMPONENT_R_BIT                                = 0x00000001,
+    VK_COLOR_COMPONENT_G_BIT                                = 0x00000002,
+    VK_COLOR_COMPONENT_B_BIT                                = 0x00000004,
+    VK_COLOR_COMPONENT_A_BIT                                = 0x00000008,
+}
+
+/// Fence creation flags
+type VkFlags VkFenceCreateFlags
+bitfield VkFenceCreateFlagBits {
+    VK_FENCE_CREATE_SIGNALED_BIT                            = 0x00000001,
+}
+
+/// Semaphore creation flags
+type VkFlags VkSemaphoreCreateFlags
+//bitfield VkSemaphoreCreateFlagBits {
+//}
+
+/// Format capability flags
+type VkFlags VkFormatFeatureFlags
+bitfield VkFormatFeatureFlagBits {
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT                     = 0x00000001,    /// Format can be used for sampled images (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)
+    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT                     = 0x00000002,    /// Format can be used for storage images (STORAGE_IMAGE descriptor type)
+    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT              = 0x00000004,    /// Format supports atomic operations in case it's used for storage images
+    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT              = 0x00000008,    /// Format can be used for uniform texel buffers (TBOs)
+    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT              = 0x00000010,    /// Format can be used for storage texel buffers (IBOs)
+    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT       = 0x00000020,    /// Format supports atomic operations in case it's used for storage texel buffers
+    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT                     = 0x00000040,    /// Format can be used for vertex buffers (VBOs)
+    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT                  = 0x00000080,    /// Format can be used for color attachment images
+    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT            = 0x00000100,    /// Format supports blending in case it's used for color attachment images
+    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT          = 0x00000200,    /// Format can be used for depth/stencil attachment images
+    VK_FORMAT_FEATURE_BLIT_SRC_BIT                          = 0x00000400,    /// Format can be used as the source image of blits with vkCommandBlitImage
+    VK_FORMAT_FEATURE_BLIT_DST_BIT                          = 0x00000800,    /// Format can be used as the destination image of blits with vkCommandBlitImage
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT       = 0x00001000,
+}
+
+/// Query control flags
+type VkFlags VkQueryControlFlags
+bitfield VkQueryControlFlagBits {
+    VK_QUERY_CONTROL_PRECISE_BIT                            = 0x00000001,
+}
+
+/// Query result flags
+type VkFlags VkQueryResultFlags
+bitfield VkQueryResultFlagBits {
+    VK_QUERY_RESULT_64_BIT                                  = 0x00000001,   /// Results of the queries are written to the destination buffer as 64-bit values
+    VK_QUERY_RESULT_WAIT_BIT                                = 0x00000002,   /// Results of the queries are waited on before proceeding with the result copy
+    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT                   = 0x00000004,   /// Besides the results of the query, the availability of the results is also written
+    VK_QUERY_RESULT_PARTIAL_BIT                             = 0x00000008,   /// Copy the partial results of the query even if the final results aren't available
+}
+
+/// Shader module creation flags
+type VkFlags VkShaderModuleCreateFlags
+//bitfield VkShaderModuleCreateFlagBits {
+//}
+
+/// Event creation flags
+type VkFlags VkEventCreateFlags
+//bitfield VkEventCreateFlagBits {
+//}
+
+/// Command buffer usage flags
+type VkFlags VkCommandBufferUsageFlags
+bitfield VkCommandBufferUsageFlagBits {
+    VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT             = 0x00000001,
+    VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT        = 0x00000002,
+    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT            = 0x00000004,
+}
+
+/// Pipeline statistics flags
+type VkFlags VkQueryPipelineStatisticFlags
+bitfield VkQueryPipelineStatisticFlagBits {
+    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT                     = 0x00000001,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT                   = 0x00000002,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT                   = 0x00000004,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT                 = 0x00000008,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT                  = 0x00000010,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT                        = 0x00000020,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT                         = 0x00000040,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT                 = 0x00000080,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT         = 0x00000100,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT  = 0x00000200,  /// Optional
+    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT                  = 0x00000400,  /// Optional
+}
+
+/// Memory mapping flags
+type VkFlags VkMemoryMapFlags
+//bitfield VkMemoryMapFlagBits {
+//}
+
+/// Bitfield of image aspects
+type VkFlags VkImageAspectFlags
+bitfield VkImageAspectFlagBits {
+    VK_IMAGE_ASPECT_COLOR_BIT                               = 0x00000001,
+    VK_IMAGE_ASPECT_DEPTH_BIT                               = 0x00000002,
+    VK_IMAGE_ASPECT_STENCIL_BIT                             = 0x00000004,
+    VK_IMAGE_ASPECT_METADATA_BIT                            = 0x00000008,
+}
+
+/// Sparse memory bind flags
+type VkFlags VkSparseMemoryBindFlags
+bitfield VkSparseMemoryBindFlagBits {
+    VK_SPARSE_MEMORY_BIND_METADATA_BIT                      = 0x00000001,
+}
+
+/// Sparse image memory requirements flags
+type VkFlags VkSparseImageFormatFlags
+bitfield VkSparseImageFormatFlagBits {
+    VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT                  = 0x00000001,  /// Image uses a single miptail region for all array slices
+    VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT                = 0x00000002,  /// Image requires mip levels to be an exact multiple of the sparse iamge block size for non-mip-tail levels.
+    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT          = 0x00000004,  /// Image uses a non-standard sparse block size
+}
+
+/// Pipeline stages
+type VkFlags VkPipelineStageFlags
+bitfield VkPipelineStageFlagBits {
+    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT                       = 0x00000001,  /// Before subsequent commands are processed
+    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT                     = 0x00000002,  /// Draw/DispatchIndirect command fetch
+    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT                      = 0x00000004,  /// Vertex/index fetch
+    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT                     = 0x00000008,  /// Vertex shading
+    VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT       = 0x00000010,  /// Tessellation control shading
+    VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT    = 0x00000020,  /// Tessellation evaluation shading
+    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT                   = 0x00000040,  /// Geometry shading
+    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT                   = 0x00000080,  /// Fragment shading
+    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT              = 0x00000100,  /// Early fragment (depth/stencil) tests
+    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT               = 0x00000200,  /// Late fragment (depth/stencil) tests
+    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT           = 0x00000400,  /// Color attachment writes
+    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT                    = 0x00000800,  /// Compute shading
+    VK_PIPELINE_STAGE_TRANSFER_BIT                          = 0x00001000,  /// Transfer/copy operations
+    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT                    = 0x00002000,
+    VK_PIPELINE_STAGE_HOST_BIT                              = 0x00004000,  /// Indicates host (CPU) is a source/sink of the dependency
+
+    VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT                      = 0x00008000,  /// All stages of the graphics pipeline
+    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT                      = 0x00010000,  /// All graphics, compute, copy, and transition commands
+}
+
+/// Render pass attachment description flags
+type VkFlags VkAttachmentDescriptionFlags
+bitfield VkAttachmentDescriptionFlagBits {
+    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT                 = 0x00000001,  /// The attachment may alias physical memory of another attachment in the same renderpass
+}
+
+/// Subpass description flags
+type VkFlags VkSubpassDescriptionFlags
+bitfield VkSubpassDescriptionFlagBits {
+}
+
+/// Command pool creation flags
+type VkFlags VkCommandPoolCreateFlags
+bitfield VkCommandPoolCreateFlagBits {
+    VK_COMMAND_POOL_CREATE_TRANSIENT_BIT                    = 0x00000001,  /// Command buffers have a short lifetime
+    VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT         = 0x00000002,  /// Command buffers may release their memory individually
+}
+
+/// Command pool reset flags
+type VkFlags VkCommandPoolResetFlags
+bitfield VkCommandPoolResetFlagBits {
+    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT             = 0x00000001,  /// Release resources owned by the pool
+}
+
+type VkFlags VkCommandBufferResetFlags
+bitfield VkCommandBufferResetFlagBits {
+    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT           = 0x00000001,  /// Release resources owned by the buffer
+}
+
+type VkFlags VkSampleCountFlags
+bitfield VkSampleCountFlagBits {
+    VK_SAMPLE_COUNT_1_BIT                                   = 0x00000001,
+    VK_SAMPLE_COUNT_2_BIT                                   = 0x00000002,
+    VK_SAMPLE_COUNT_4_BIT                                   = 0x00000004,
+    VK_SAMPLE_COUNT_8_BIT                                   = 0x00000008,
+    VK_SAMPLE_COUNT_16_BIT                                  = 0x00000010,
+    VK_SAMPLE_COUNT_32_BIT                                  = 0x00000020,
+    VK_SAMPLE_COUNT_64_BIT                                  = 0x00000040,
+}
+
+type VkFlags VkStencilFaceFlags
+bitfield VkStencilFaceFlagBits {
+    VK_STENCIL_FACE_FRONT_BIT                               = 0x00000001,   /// Front face
+    VK_STENCIL_FACE_BACK_BIT                                = 0x00000002,   /// Back face
+    VK_STENCIL_FRONT_AND_BACK                               = 0x00000003,
+}
+
+/// Instance creation flags
+type VkFlags VkInstanceCreateFlags
+//bitfield VkInstanceCreateFlagBits {
+//}
+
+/// Device creation flags
+type VkFlags VkDeviceCreateFlags
+//bitfield VkDeviceCreateFlagBits {
+//}
+
+/// Device queue creation flags
+type VkFlags VkDeviceQueueCreateFlags
+//bitfield VkDeviceQueueCreateFlagBits {
+//}
+
+/// Query pool creation flags
+type VkFlags VkQueryPoolCreateFlags
+//bitfield VkQueryPoolCreateFlagBits {
+//}
+
+/// Buffer view creation flags
+type VkFlags VkBufferViewCreateFlags
+//bitfield VkBufferViewCreateFlagBits {
+//}
+
+/// Pipeline cache creation flags
+type VkFlags VkPipelineCacheCreateFlags
+//bitfield VkPipelineCacheCreateFlagBits {
+//}
+
+/// Pipeline shader stage creation flags
+type VkFlags VkPipelineShaderStageCreateFlags
+//bitfield VkPipelineShaderStageCreateFlagBits {
+//}
+
+/// Descriptor set layout creation flags
+type VkFlags VkDescriptorSetLayoutCreateFlags
+//bitfield VkDescriptorSetLayoutCreateFlagBits {
+//}
+
+/// Pipeline vertex input state creation flags
+type VkFlags VkPipelineVertexInputStateCreateFlags
+//bitfield VkPipelineVertexInputStateCreateFlagBits {
+//}
+
+/// Pipeline input assembly state creation flags
+type VkFlags VkPipelineInputAssemblyStateCreateFlags
+//bitfield VkPipelineInputAssemblyStateCreateFlagBits {
+//}
+
+/// Tessellation state creation flags
+type VkFlags VkPipelineTessellationStateCreateFlags
+//bitfield VkPipelineTessellationStateCreateFlagBits {
+//}
+
+/// Viewport state creation flags
+type VkFlags VkPipelineViewportStateCreateFlags
+//bitfield VkPipelineViewportStateCreateFlagBits {
+//}
+
+/// Rasterization state creation flags
+type VkFlags VkPipelineRasterizationStateCreateFlags
+//bitfield VkPipelineRasterizationStateCreateFlagBits {
+//}
+
+/// Multisample state creation flags
+type VkFlags VkPipelineMultisampleStateCreateFlags
+//bitfield VkPipelineMultisampleStateCreateFlagBits {
+//}
+
+/// Color blend state creation flags
+type VkFlags VkPipelineColorBlendStateCreateFlags
+//bitfield VkPipelineColorBlendStateCreateFlagBits {
+//}
+
+/// Depth/stencil state creation flags
+type VkFlags VkPipelineDepthStencilStateCreateFlags
+//bitfield VkPipelineDepthStencilStateCreateFlagBits {
+//}
+
+/// Dynamic state creation flags
+type VkFlags VkPipelineDynamicStateCreateFlags
+//bitfield VkPipelineDynamicStateCreateFlagBits {
+//}
+
+/// Pipeline layout creation flags
+type VkFlags VkPipelineLayoutCreateFlags
+//bitfield VkPipelineLayoutCreateFlagBits {
+//}
+
+/// Sampler creation flags
+type VkFlags VkSamplerCreateFlags
+//bitfield VkSamplerCreateFlagBits {
+//}
+
+/// Render pass creation flags
+type VkFlags VkRenderPassCreateFlags
+//bitfield VkRenderPassCreateFlagBits {
+//}
+
+/// Framebuffer creation flags
+type VkFlags VkFramebufferCreateFlags
+//bitfield VkFramebufferCreateFlagBits {
+//}
+
+/// Dependency flags
+type VkFlags VkDependencyFlags
+bitfield VkDependencyFlagBits {
+    VK_DEPENDENCY_BY_REGION_BIT                             = 0x00000001,
+}
+
+/// Cull mode flags
+type VkFlags VkCullModeFlags
+bitfield VkCullModeFlagBits {
+    VK_CULL_MODE_NONE                                       = 0x00000000,
+    VK_CULL_MODE_FRONT_BIT                                  = 0x00000001,
+    VK_CULL_MODE_BACK_BIT                                   = 0x00000002,
+    VK_CULL_MODE_FRONT_AND_BACK                             = 0x00000003,
+}
+
+@extension("VK_KHR_surface")
+type VkFlags VkSurfaceTransformFlagsKHR
+@extension("VK_KHR_surface")
+bitfield VkSurfaceTransformFlagBitsKHR {
+    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR                       = 0x00000001,
+    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR                      = 0x00000002,
+    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR                     = 0x00000004,
+    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR                     = 0x00000008,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR              = 0x00000010,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR    = 0x00000020,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR   = 0x00000040,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR   = 0x00000080,
+    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR                        = 0x00000100,
+}
+
+@extension("VK_KHR_surface")
+type VkFlags VkCompositeAlphaFlagsKHR
+@extension("VK_KHR_surface")
+bitfield VkCompositeAlphaFlagBitsKHR {
+    VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR                       = 0x00000001,
+    VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR               = 0x00000002,
+    VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR              = 0x00000004,
+    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR                      = 0x00000008,
+}
+
+@extension("VK_KHR_swapchain")
+type VkFlags VkSwapchainCreateFlagsKHR
+//@extension("VK_KHR_swapchain")
+//bitfield VkSwapchainCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_display")
+type VkFlags VkDisplayPlaneAlphaFlagsKHR
+@extension("VK_KHR_display")
+bitfield VkDisplayPlaneAlphaFlagBitsKHR {
+    VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR                   = 0x00000001,
+    VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR                   = 0x00000002,
+    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR                = 0x00000004,
+    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR  = 0x00000008,
+}
+
+@extension("VK_KHR_display")
+type VkFlags VkDisplaySurfaceCreateFlagsKHR
+//@extension("VK_KHR_display")
+//bitfield VkDisplaySurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_display")
+type VkFlags VkDisplayModeCreateFlagsKHR
+//@extension("VK_KHR_display")
+//bitfield VkDisplayModeCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_xlib_surface")
+type VkFlags VkXlibSurfaceCreateFlagsKHR
+//@extension("VK_KHR_xlib_surface")
+//bitfield VkXlibSurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_xcb_surface")
+type VkFlags VkXcbSurfaceCreateFlagsKHR
+//@extension("VK_KHR_xcb_surface")
+//bitfield VkXcbSurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_wayland_surface")
+type VkFlags VkWaylandSurfaceCreateFlagsKHR
+//@extension("VK_KHR_wayland_surface")
+//bitfield VkWaylandSurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_mir_surface")
+type VkFlags VkMirSurfaceCreateFlagsKHR
+//@extension("VK_KHR_mir_surface")
+//bitfield VkMirSurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_android_surface")
+type VkFlags VkAndroidSurfaceCreateFlagsKHR
+//@extension("VK_KHR_android_surface")
+//bitfield VkAndroidSurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_KHR_win32_surface")
+type VkFlags VkWin32SurfaceCreateFlagsKHR
+//@extension("VK_KHR_win32_surface")
+//bitfield VkWin32SurfaceCreateFlagBitsKHR {
+//}
+
+@extension("VK_EXT_debug_report")
+type VkFlags VkDebugReportFlagsEXT
+@extension("VK_EXT_debug_report")
+bitfield VkDebugReportFlagBitsEXT {
+    VK_DEBUG_REPORT_INFORMATION_BIT_EXT                     = 0x00000001,
+    VK_DEBUG_REPORT_WARNING_BIT_EXT                         = 0x00000002,
+    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT             = 0x00000004,
+    VK_DEBUG_REPORT_ERROR_BIT_EXT                           = 0x00000008,
+    VK_DEBUG_REPORT_DEBUG_BIT_EXT                           = 0x00000010,
+}
+
+
+//////////////////
+//  Structures  //
+//////////////////
+
+class VkOffset2D {
+    s32                                         x
+    s32                                         y
+}
+
+class VkOffset3D {
+    s32                                         x
+    s32                                         y
+    s32                                         z
+}
+
+class VkExtent2D {
+    u32                                         width
+    u32                                         height
+}
+
+class VkExtent3D {
+    u32                                         width
+    u32                                         height
+    u32                                         depth
+}
+
+class VkViewport {
+    f32                                         x
+    f32                                         y
+    f32                                         width
+    f32                                         height
+    f32                                         minDepth
+    f32                                         maxDepth
+}
+
+class VkRect2D {
+    VkOffset2D                                  offset
+    VkExtent2D                                  extent
+}
+
+class VkClearRect {
+    VkRect2D                                    rect
+    u32                                         baseArrayLayer
+    u32                                         layerCount
+}
+
+class VkComponentMapping {
+    VkComponentSwizzle                          r
+    VkComponentSwizzle                          g
+    VkComponentSwizzle                          b
+    VkComponentSwizzle                          a
+}
+
+class VkPhysicalDeviceProperties {
+    u32                                         apiVersion
+    u32                                         driverVersion
+    u32                                         vendorID
+    u32                                         deviceID
+    VkPhysicalDeviceType                        deviceType
+    char[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]      deviceName
+    u8[VK_UUID_SIZE]                            pipelineCacheUUID
+    VkPhysicalDeviceLimits                      limits
+    VkPhysicalDeviceSparseProperties            sparseProperties
+}
+
+class VkExtensionProperties {
+    char[VK_MAX_EXTENSION_NAME_SIZE]            extensionName      /// extension name
+    u32                                         specVersion        /// version of the extension specification implemented
+}
+
+class VkLayerProperties {
+    char[VK_MAX_EXTENSION_NAME_SIZE]            layerName               /// layer name
+    u32                                         specVersion             /// version of the layer specification implemented
+    u32                                         implementationVersion   /// build or release version of the layer's library
+    char[VK_MAX_DESCRIPTION_SIZE]               description             /// Free-form description of the layer
+}
+
+class VkSubmitInfo {
+    VkStructureType                             sType              /// Type of structure. Should be VK_STRUCTURE_TYPE_SUBMIT_INFO
+    const void*                                 pNext              /// Next structure in chain
+    u32                                         waitSemaphoreCount
+    const VkSemaphore*                          pWaitSemaphores
+    const VkPipelineStageFlags*                 pWaitDstStageMask
+    u32                                         commandBufferCount
+    const VkCommandBuffer*                      pCommandBuffers
+    u32                                         signalSemaphoreCount
+    const VkSemaphore*                          pSignalSemaphores
+}
+
+class VkApplicationInfo {
+    VkStructureType                             sType              /// Type of structure. Should be VK_STRUCTURE_TYPE_APPLICATION_INFO
+    const void*                                 pNext              /// Next structure in chain
+    const char*                                 pApplicationName
+    u32                                         applicationVersion
+    const char*                                 pEngineName
+    u32                                         engineVersion
+    u32                                         apiVersion
+}
+
+class VkAllocationCallbacks {
+    void*                                       pUserData
+    PFN_vkAllocationFunction                    pfnAllocation
+    PFN_vkReallocationFunction                  pfnReallocation
+    PFN_vkFreeFunction                          pfnFree
+    PFN_vkInternalAllocationNotification        pfnInternalAllocation
+    PFN_vkInternalFreeNotification              pfnInternalFree
+}
+
+class VkDeviceQueueCreateInfo {
+    VkStructureType                             sStype                    /// Should be VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
+    const void*                                 pNext                     /// Pointer to next structure
+    VkDeviceQueueCreateFlags                    flags
+    u32                                         queueFamilyIndex
+    u32                                         queueCount
+    const f32*                                  pQueuePriorities
+}
+
+class VkDeviceCreateInfo {
+    VkStructureType                             sType                      /// Should be VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
+    const void*                                 pNext                      /// Pointer to next structure
+    VkDeviceCreateFlags                         flags
+    u32                                         queueCreateInfoCount
+    const VkDeviceQueueCreateInfo*              pQueueCreateInfos
+    u32                                         enabledLayerCount
+    const char* const*                          ppEnabledLayerNames        /// Ordered list of layer names to be enabled
+    u32                                         enabledExtensionCount
+    const char* const*                          ppEnabledExtensionNames
+    const VkPhysicalDeviceFeatures*             pEnabledFeatures
+}
+
+class VkInstanceCreateInfo {
+    VkStructureType                             sType                      /// Should be VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
+    const void*                                 pNext                      /// Pointer to next structure
+    VkInstanceCreateFlags                       flags
+    const VkApplicationInfo*                    pApplicationInfo
+    u32                                         enabledLayerCount
+    const char* const*                          ppEnabledLayerNames        /// Ordered list of layer names to be enabled
+    u32                                         enabledExtensionCount
+    const char* const*                          ppEnabledExtensionNames    /// Extension names to be enabled
+}
+
+class VkQueueFamilyProperties {
+    VkQueueFlags                                queueFlags                 /// Queue flags
+    u32                                         queueCount
+    u32                                         timestampValidBits
+    VkExtent3D                                  minImageTransferGranularity
+}
+
+class VkPhysicalDeviceMemoryProperties {
+    u32                                         memoryTypeCount
+    VkMemoryType[VK_MAX_MEMORY_TYPES]           memoryTypes
+    u32                                         memoryHeapCount
+    VkMemoryHeap[VK_MAX_MEMORY_HEAPS]           memoryHeaps
+}
+
+class VkMemoryAllocateInfo {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
+    const void*                                 pNext                      /// Pointer to next structure
+    VkDeviceSize                                allocationSize             /// Size of memory allocation
+    u32                                         memoryTypeIndex            /// Index of the of the memory type to allocate from
+}
+
+class VkMemoryRequirements {
+    VkDeviceSize                                size                       /// Specified in bytes
+    VkDeviceSize                                alignment                  /// Specified in bytes
+    u32                                         memoryTypeBits             /// Bitfield of the allowed memory type indices into memoryTypes[] for this object
+}
+
+class VkSparseImageFormatProperties {
+    VkImageAspectFlagBits                       aspectMask
+    VkExtent3D                                  imageGranularity
+    VkSparseImageFormatFlags                    flags
+}
+
+class VkSparseImageMemoryRequirements {
+    VkSparseImageFormatProperties               formatProperties
+    u32                                         imageMipTailFirstLod
+    VkDeviceSize                                imageMipTailSize           /// Specified in bytes, must be a multiple of image block size / alignment
+    VkDeviceSize                                imageMipTailOffset         /// Specified in bytes, must be a multiple of image block size / alignment
+    VkDeviceSize                                imageMipTailStride         /// Specified in bytes, must be a multiple of image block size / alignment
+}
+
+class VkMemoryType {
+    VkMemoryPropertyFlags                       propertyFlags              /// Memory properties of this memory type
+    u32                                         heapIndex                  /// Index of the memory heap allocations of this memory type are taken from
+}
+
+class VkMemoryHeap {
+    VkDeviceSize                                size                       /// Available memory in the heap
+    VkMemoryHeapFlags                           flags                      /// Flags for the heap
+}
+
+class VkMappedMemoryRange {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
+    const void*                                 pNext                      /// Pointer to next structure
+    VkDeviceMemory                              memory                     /// Mapped memory object
+    VkDeviceSize                                offset                     /// Offset within the mapped memory the range starts from
+    VkDeviceSize                                size                       /// Size of the range within the mapped memory
+}
+
+class VkFormatProperties {
+    VkFormatFeatureFlags                        linearTilingFeatures       /// Format features in case of linear tiling
+    VkFormatFeatureFlags                        optimalTilingFeatures      /// Format features in case of optimal tiling
+    VkFormatFeatureFlags                        bufferFeatures             /// Format features supported by buffers
+}
+
+class VkImageFormatProperties {
+    VkExtent3D                                  maxExtent                  /// max image dimensions for this resource type
+    u32                                         maxMipLevels               /// max number of mipmap levels for this resource type
+    u32                                         maxArrayLayers             /// max array layers for this resource type
+    VkSampleCountFlags                          sampleCounts               /// supported sample counts for this resource type
+    VkDeviceSize                                maxResourceSize            /// max size (in bytes) of this resource type
+}
+
+class VkDescriptorImageInfo {
+    VkSampler                                   sampler
+    VkImageView                                 imageView
+    VkImageLayout                               imageLayout
+}
+
+class VkDescriptorBufferInfo {
+    VkBuffer                                    buffer                     /// Buffer used for this descriptor when the descriptor is UNIFORM_BUFFER[_DYNAMIC]
+    VkDeviceSize                                offset                     /// Base offset from buffer start in bytes to update in the descriptor set.
+    VkDeviceSize                                range                      /// Size in bytes of the buffer resource for this descriptor update.
+}
+
+class VkWriteDescriptorSet {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
+    const void*                                 pNext                      /// Pointer to next structure
+    VkDescriptorSet                             dstSet                     /// Destination descriptor set
+    u32                                         dstBinding                 /// Binding within the destination descriptor set to write
+    u32                                         dstArrayElement            /// Array element within the destination binding to write
+    u32                                         descriptorCount            /// Number of descriptors to write (determines the size of the array pointed by <pDescriptors>)
+    VkDescriptorType                            descriptorType             /// Descriptor type to write (determines which fields of the array pointed by <pDescriptors> are going to be used)
+    const VkDescriptorImageInfo*                pImageInfo
+    const VkDescriptorBufferInfo*               pBufferInfo
+    const VkBufferView*                         pTexelBufferView
+}
+
+class VkCopyDescriptorSet {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET
+    const void*                                 pNext                      /// Pointer to next structure
+    VkDescriptorSet                             srcSet                     /// Source descriptor set
+    u32                                         srcBinding                 /// Binding within the source descriptor set to copy from
+    u32                                         srcArrayElement            /// Array element within the source binding to copy from
+    VkDescriptorSet                             dstSet                     /// Destination descriptor set
+    u32                                         dstBinding                 /// Binding within the destination descriptor set to copy to
+    u32                                         dstArrayElement            /// Array element within the destination binding to copy to
+    u32                                         descriptorCount            /// Number of descriptors to copy
+}
+
+class VkBufferCreateInfo {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
+    const void*                                 pNext                      /// Pointer to next structure.
+    VkBufferCreateFlags                         flags                      /// Buffer creation flags
+    VkDeviceSize                                size                       /// Specified in bytes
+    VkBufferUsageFlags                          usage                      /// Buffer usage flags
+    VkSharingMode                               sharingMode
+    u32                                         queueFamilyIndexCount
+    const u32*                                  pQueueFamilyIndices
+}
+
+class VkBufferViewCreateInfo {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO
+    const void*                                 pNext                      /// Pointer to next structure.
+    VkBufferViewCreateFlags                     flags
+    VkBuffer                                    buffer
+    VkFormat                                    format                     /// Optionally specifies format of elements
+    VkDeviceSize                                offset                     /// Specified in bytes
+    VkDeviceSize                                range                      /// View size specified in bytes
+}
+
+class VkImageSubresource {
+    VkImageAspectFlagBits                       aspectMask
+    u32                                         mipLevel
+    u32                                         arrayLayer
+}
+
+class VkImageSubresourceRange {
+    VkImageAspectFlags                          aspectMask
+    u32                                         baseMipLevel
+    u32                                         levelCount
+    u32                                         baseArrayLayer
+    u32                                         layerCount
+}
+
+class VkMemoryBarrier {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_MEMORY_BARRIER
+    const void*                                 pNext                      /// Pointer to next structure.
+    VkAccessFlags                               srcAccessMask
+    VkAccessFlags                               dstAccessMask
+}
+
+class VkBufferMemoryBarrier {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
+    const void*                                 pNext                      /// Pointer to next structure.
+    VkAccessFlags                               srcAccessMask
+    VkAccessFlags                               dstAccessMask
+    u32                                         srcQueueFamilyIndex        /// Queue family to transition ownership from
+    u32                                         dstQueueFamilyIndex        /// Queue family to transition ownership to
+    VkBuffer                                    buffer                     /// Buffer to sync
+    VkDeviceSize                                offset                     /// Offset within the buffer to sync
+    VkDeviceSize                                size                       /// Amount of bytes to sync
+}
+
+class VkImageMemoryBarrier {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
+    const void*                                 pNext                      /// Pointer to next structure.
+    VkAccessFlags                               srcAccessMask
+    VkAccessFlags                               dstAccessMask
+    VkImageLayout                               oldLayout                  /// Current layout of the image
+    VkImageLayout                               newLayout                  /// New layout to transition the image to
+    u32                                         srcQueueFamilyIndex        /// Queue family to transition ownership from
+    u32                                         dstQueueFamilyIndex        /// Queue family to transition ownership to
+    VkImage                                     image                      /// Image to sync
+    VkImageSubresourceRange                     subresourceRange           /// Subresource range to sync
+}
+
+class VkImageCreateInfo {
+    VkStructureType                             sType                      /// Must be VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
+    const void*                                 pNext                      /// Pointer to next structure.
+    VkImageCreateFlags                          flags                      /// Image creation flags
+    VkImageType                                 imageType
+    VkFormat                                    format
+    VkExtent3D                                  extent
+    u32                                         mipLevels
+    u32                                         arrayLayers
+    VkSampleCountFlagBits                       samples
+    VkImageTiling                               tiling
+    VkImageUsageFlags                           usage                      /// Image usage flags
+    VkSharingMode                               sharingMode                /// Cross-queue-family sharing mode
+    u32                                         queueFamilyIndexCount      /// Number of queue families to share across
+    const u32*                                  pQueueFamilyIndices        /// Array of queue family indices to share across
+    VkImageLayout                               initialLayout              /// Initial image layout for all subresources
+}
+
+class VkSubresourceLayout {
+    VkDeviceSize                                offset                 /// Specified in bytes
+    VkDeviceSize                                size                   /// Specified in bytes
+    VkDeviceSize                                rowPitch               /// Specified in bytes
+    VkDeviceSize                                arrayPitch             /// Specified in bytes
+    VkDeviceSize                                depthPitch             /// Specified in bytes
+}
+
+class VkImageViewCreateInfo {
+    VkStructureType                             sType                  /// Must be VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO
+    const void*                                 pNext                  /// Pointer to next structure
+    VkImageViewCreateFlags                      flags
+    VkImage                                     image
+    VkImageViewType                             viewType
+    VkFormat                                    format
+    VkComponentMapping                          components
+    VkImageSubresourceRange                     subresourceRange
+}
+
+class VkBufferCopy {
+    VkDeviceSize                                srcOffset              /// Specified in bytes
+    VkDeviceSize                                dstOffset              /// Specified in bytes
+    VkDeviceSize                                size                   /// Specified in bytes
+}
+
+class VkSparseMemoryBind {
+    VkDeviceSize                                resourceOffset        /// Specified in bytes
+    VkDeviceSize                                size                  /// Specified in bytes
+    VkDeviceMemory                              memory
+    VkDeviceSize                                memoryOffset          /// Specified in bytes
+    VkSparseMemoryBindFlags                     flags
+}
+
+class VkSparseImageMemoryBind {
+    VkImageSubresource                          subresource
+    VkOffset3D                                  offset
+    VkExtent3D                                  extent
+    VkDeviceMemory                              memory
+    VkDeviceSize                                memoryOffset          /// Specified in bytes
+    VkSparseMemoryBindFlags                     flags
+}
+
+class VkSparseBufferMemoryBindInfo {
+    VkBuffer                                    buffer
+    u32                                         bindCount
+    const VkSparseMemoryBind*                   pBinds
+}
+
+class VkSparseImageOpaqueMemoryBindInfo {
+    VkImage                                     image
+    u32                                         bindCount
+    const VkSparseMemoryBind*                   pBinds
+}
+
+class VkSparseImageMemoryBindInfo {
+    VkImage                                     image
+    u32                                         bindCount
+    const VkSparseMemoryBind*                   pBinds
+}
+
+class VkBindSparseInfo {
+    VkStructureType                             sType                 /// Must be VK_STRUCTURE_TYPE_BIND_SPARSE_INFO
+    const void*                                 pNext
+    u32                                         waitSemaphoreCount
+    const VkSemaphore*                          pWaitSemaphores
+    u32                                         numBufferBinds
+    const VkSparseBufferMemoryBindInfo*         pBufferBinds
+    u32                                         numImageOpaqueBinds
+    const VkSparseImageOpaqueMemoryBindInfo*    pImageOpaqueBinds
+    u32                                         numImageBinds
+    const VkSparseImageMemoryBindInfo*          pImageBinds
+    u32                                         signalSemaphoreCount
+    const VkSemaphore*                          pSignalSemaphores
+}
+
+class VkImageSubresourceLayers {
+    VkImageAspectFlags                          aspectMask
+    u32                                         mipLevel
+    u32                                         baseArrayLayer
+    u32                                         layerCount
+}
+
+class VkImageCopy {
+    VkImageSubresourceLayers                    srcSubresource
+    VkOffset3D                                  srcOffset             /// Specified in pixels for both compressed and uncompressed images
+    VkImageSubresourceLayers                    dstSubresource
+    VkOffset3D                                  dstOffset             /// Specified in pixels for both compressed and uncompressed images
+    VkExtent3D                                  extent                /// Specified in pixels for both compressed and uncompressed images
+}
+
+class VkImageBlit {
+    VkImageSubresourceLayers                    srcSubresource
+    VkOffset3D[2]                               srcOffsets
+    VkImageSubresourceLayers                    dstSubresource
+    VkOffset3D[2]                               dstOffsets
+}
+
+class VkBufferImageCopy {
+    VkDeviceSize                                bufferOffset           /// Specified in bytes
+    u32                                         bufferRowLength        /// Specified in texels
+    u32                                         bufferImageHeight
+    VkImageSubresourceLayers                    imageSubresource
+    VkOffset3D                                  imageOffset            /// Specified in pixels for both compressed and uncompressed images
+    VkExtent3D                                  imageExtent            /// Specified in pixels for both compressed and uncompressed images
+}
+
+class VkImageResolve {
+    VkImageSubresourceLayers                    srcSubresource
+    VkOffset3D                                  srcOffset
+    VkImageSubresourceLayers                    dstSubresource
+    VkOffset3D                                  dstOffset
+    VkExtent3D                                  extent
+}
+
+class VkShaderModuleCreateInfo {
+    VkStructureType                             sType                  /// Must be VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO
+    const void*                                 pNext                  /// Pointer to next structure
+    VkShaderModuleCreateFlags                   flags                  /// Reserved
+    platform.size_t                             codeSize               /// Specified in bytes
+    const u32*                                  pCode                  /// Binary code of size codeSize
+}
+
+class VkDescriptorSetLayoutBinding {
+    u32                                         binding
+    VkDescriptorType                            descriptorType     /// Type of the descriptors in this binding
+    u32                                         descriptorCount    /// Number of descriptors in this binding
+    VkShaderStageFlags                          stageFlags         /// Shader stages this binding is visible to
+    const VkSampler*                            pImmutableSamplers /// Immutable samplers (used if descriptor type is SAMPLER or COMBINED_IMAGE_SAMPLER, is either NULL or contains <count> number of elements)
+}
+
+class VkDescriptorSetLayoutCreateInfo {
+    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
+    const void*                                 pNext              /// Pointer to next structure
+    VkDescriptorSetLayoutCreateFlags            flags
+    u32                                         bindingCount       /// Number of bindings in the descriptor set layout
+    const VkDescriptorSetLayoutBinding*         pBindings          /// Array of descriptor set layout bindings
+}
+
+class VkDescriptorPoolSize {
+    VkDescriptorType                            type
+    u32                                         descriptorCount
+}
+
+class VkDescriptorPoolCreateInfo {
+    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO
+    const void*                                 pNext              /// Pointer to next structure
+    VkDescriptorPoolCreateFlags                 flags
+    u32                                         maxSets
+    u32                                         poolSizeCount
+    const VkDescriptorPoolSize*                 pPoolSizes
+}
+
+class VkDescriptorSetAllocateInfo {
+    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO
+    const void*                                 pNext              /// Pointer to next structure
+    VkDescriptorPool                            descriptorPool
+    u32                                         setCount
+    const VkDescriptorSetLayout*                pSetLayouts
+}
+
+class VkSpecializationMapEntry {
+    u32                                         constantID         /// The SpecConstant ID specified in the BIL
+    u32                                         offset             /// Offset of the value in the data block
+    platform.size_t                             size               /// Size in bytes of the SpecConstant
+}
+
+class VkSpecializationInfo {
+    u32                                         mapEntryCount      /// Number of entries in the map
+    const VkSpecializationMapEntry*             pMapEntries        /// Array of map entries
+    platform.size_t                             dataSize           /// Size in bytes of pData
+    const void*                                 pData              /// Pointer to SpecConstant data
+}
+
+class VkPipelineShaderStageCreateInfo {
+    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
+    const void*                                 pNext              /// Pointer to next structure
+    VkPipelineShaderStageCreateFlags            flags
+    VkShaderStageFlagBits                       stage
+    VkShaderModule                              module
+    const char*                                 pName
+    const VkSpecializationInfo*                 pSpecializationInfo
+}
+
+class VkComputePipelineCreateInfo {
+    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO
+    const void*                                 pNext              /// Pointer to next structure
+    VkPipelineCreateFlags                       flags              /// Pipeline creation flags
+    VkPipelineShaderStageCreateInfo             stage
+    VkPipelineLayout                            layout             /// Interface layout of the pipeline
+    VkPipeline                                  basePipelineHandle /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of
+    s32                                         basePipelineIndex  /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of
+}
+
+class VkVertexInputBindingDescription {
+    u32                                         binding               /// Vertex buffer binding id
+    u32                                         stride                /// Distance between vertices in bytes (0 = no advancement)
+    VkVertexInputRate                           inputRate             /// Rate at which binding is incremented
+}
+
+class VkVertexInputAttributeDescription {
+    u32                                         location              /// location of the shader vertex attrib
+    u32                                         binding               /// Vertex buffer binding id
+    VkFormat                                    format                /// format of source data
+    u32                                         offset                /// Offset of first element in bytes from base of vertex
+}
+
+class VkPipelineVertexInputStateCreateInfo {
+    VkStructureType                             sType                           /// Should be VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
+    const void*                                 pNext                           /// Pointer to next structure
+    VkPipelineVertexInputStateCreateFlags       flags
+    u32                                         vertexBindingDescriptionCount   /// number of bindings
+    const VkVertexInputBindingDescription*      pVertexBindingDescriptions
+    u32                                         vertexAttributeDescriptionCount /// number of attributes
+    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
+}
+
+class VkPipelineInputAssemblyStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineInputAssemblyStateCreateFlags     flags
+    VkPrimitiveTopology                         topology
+    VkBool32                                    primitiveRestartEnable
+}
+
+class VkPipelineTessellationStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineTessellationStateCreateFlags      flags
+    u32                                         patchControlPoints
+}
+
+class VkPipelineViewportStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineViewportStateCreateFlags          flags
+    u32                                         viewportCount
+    const VkViewport*                           pViewports
+    u32                                         scissorCount
+    const VkRect2D*                             pScissors
+}
+
+class VkPipelineRasterizationStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineRasterizationStateCreateFlags     flags
+    VkBool32                                    depthClampEnable
+    VkBool32                                    rasterizerDiscardEnable
+    VkPolygonMode                               polygonMode                   /// optional (GL45)
+    VkCullModeFlags                             cullMode
+    VkFrontFace                                 frontFace
+    VkBool32                                    depthBiasEnable
+    f32                                         depthBiasConstantFactor
+    f32                                         depthBiasClamp
+    f32                                         depthBiasSlopeFactor
+    f32                                         lineWidth
+}
+
+class VkPipelineMultisampleStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineMultisampleStateCreateFlags       flags
+    VkSampleCountFlagBits                       rasterizationSamples       /// Number of samples used for rasterization
+    VkBool32                                    sampleShadingEnable        /// optional (GL45)
+    f32                                         minSampleShading           /// optional (GL45)
+    const VkSampleMask*                         pSampleMask
+    VkBool32                                    alphaToCoverageEnable
+    VkBool32                                    alphaToOneEnable
+}
+
+class VkPipelineColorBlendAttachmentState {
+    VkBool32                                    blendEnable
+    VkBlendFactor                               srcColorBlendFactor
+    VkBlendFactor                               dstColorBlendFactor
+    VkBlendOp                                   colorBlendOp
+    VkBlendFactor                               srcAlphaBlendFactor
+    VkBlendFactor                               dstAlphaBlendFactor
+    VkBlendOp                                   alphaBlendOp
+    VkColorComponentFlags                       colorWriteMask
+}
+
+class VkPipelineColorBlendStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineColorBlendStateCreateFlags        flags
+    VkBool32                                    logicOpEnable
+    VkLogicOp                                   logicOp
+    u32                                         attachmentCount    /// # of pAttachments
+    const VkPipelineColorBlendAttachmentState*  pAttachments
+    f32[4]                                      blendConstants
+}
+
+class VkStencilOpState {
+    VkStencilOp                                 failOp
+    VkStencilOp                                 passOp
+    VkStencilOp                                 depthFailOp
+    VkCompareOp                                 compareOp
+    u32                                         compareMask
+    u32                                         writeMask
+    u32                                         reference
+}
+
+class VkPipelineDepthStencilStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineDepthStencilStateCreateFlags      flags
+    VkBool32                                    depthTestEnable
+    VkBool32                                    depthWriteEnable
+    VkCompareOp                                 depthCompareOp
+    VkBool32                                    depthBoundsTestEnable  /// optional (depth_bounds_test)
+    VkBool32                                    stencilTestEnable
+    VkStencilOpState                            front
+    VkStencilOpState                            back
+    f32                                         minDepthBounds
+    f32                                         maxDepthBounds
+}
+
+class VkPipelineDynamicStateCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkPipelineDynamicStateCreateFlags           flags
+    u32                                         dynamicStateCount
+    const VkDynamicState*                       pDynamicStates
+}
+
+class VkGraphicsPipelineCreateInfo {
+    VkStructureType                                 sType               /// Must be VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
+    const void*                                     pNext               /// Pointer to next structure
+    VkPipelineCreateFlags                           flags               /// Pipeline creation flags
+    u32                                             stageCount
+    const VkPipelineShaderStageCreateInfo*          pStages             /// One entry for each active shader stage
+    const VkPipelineVertexInputStateCreateInfo*     pVertexInputState
+    const VkPipelineInputAssemblyStateCreateInfo*   pInputAssemblyState
+    const VkPipelineTessellationStateCreateInfo*    pTessellationState
+    const VkPipelineViewportStateCreateInfo*        pViewportState
+    const VkPipelineRasterizationStateCreateInfo*   pRasterizationState
+    const VkPipelineMultisampleStateCreateInfo*     pMultisampleState
+    const VkPipelineDepthStencilStateCreateInfo*    pDepthStencilState
+    const VkPipelineColorBlendStateCreateInfo*      pColorBlendState
+    const VkPipelineDynamicStateCreateInfo*         pDynamicState
+    VkPipelineLayout                                layout              /// Interface layout of the pipeline
+    VkRenderPass                                    renderPass
+    u32                                             subpass
+    VkPipeline                                      basePipelineHandle  /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of
+    s32                                             basePipelineIndex   /// If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of
+}
+
+class VkPipelineCacheCreateInfo {
+    VkStructureType                             sType                 /// Must be VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
+    const void*                                 pNext                 /// Pointer to next structure
+    VkPipelineCacheCreateFlags                  flags
+    platform.size_t                             initialDataSize       /// Size of initial data to populate cache, in bytes
+    const void*                                 pInitialData          /// Initial data to populate cache
+}
+
+class VkPushConstantRange {
+    VkShaderStageFlags                          stageFlags   /// Which stages use the range
+    u32                                         offset       /// Start of the range, in bytes
+    u32                                         size        /// Length of the range, in bytes
+}
+
+class VkPipelineLayoutCreateInfo {
+    VkStructureType                             sType                   /// Must be VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
+    const void*                                 pNext                   /// Pointer to next structure
+    VkPipelineLayoutCreateFlags                 flags
+    u32                                         descriptorSetCount      /// Number of descriptor sets interfaced by the pipeline
+    const VkDescriptorSetLayout*                pSetLayouts             /// Array of <setCount> number of descriptor set layout objects defining the layout of the
+    u32                                         pushConstantRangeCount  /// Number of push-constant ranges used by the pipeline
+    const VkPushConstantRange*                  pPushConstantRanges     /// Array of pushConstantRangeCount number of ranges used by various shader stages
+}
+
+class VkSamplerCreateInfo {
+    VkStructureType                             sType          /// Must be VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO
+    const void*                                 pNext          /// Pointer to next structure
+    VkSamplerCreateFlags                        flags
+    VkFilter                                    magFilter      /// Filter mode for magnification
+    VkFilter                                    minFilter      /// Filter mode for minifiation
+    VkSamplerMipmapMode                         mipmapMode     /// Mipmap selection mode
+    VkSamplerAddressMode                        addressModeU
+    VkSamplerAddressMode                        addressModeV
+    VkSamplerAddressMode                        addressModeW
+    f32                                         mipLodBias
+    VkBool32                                    anisotropyEnable
+    f32                                         maxAnisotropy
+    VkBool32                                    compareEnable
+    VkCompareOp                                 compareOp
+    f32                                         minLod
+    f32                                         maxLod
+    VkBorderColor                               borderColor
+    VkBool32                                    unnormalizedCoordinates
+}
+
+class VkCommandPoolCreateInfo {
+    VkStructureType                             sType            /// Must be VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
+    const void*                                 pNext            /// Pointer to next structure
+    VkCommandPoolCreateFlags                    flags            /// Command pool creation flags
+    u32                                         queueFamilyIndex
+}
+
+class VkCommandBufferAllocateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkCommandPool                               commandPool
+    VkCommandBufferLevel                        level
+    u32                                         commandBufferCount
+}
+
+class VkCommandBufferInheritanceInfo {
+    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO
+    const void*                                 pNext       /// Pointer to next structure
+    VkRenderPass                                renderPass  /// Render pass for secondary command buffers
+    u32                                         subpass
+    VkFramebuffer                               framebuffer /// Framebuffer for secondary command buffers
+    VkBool32                                    occlusionQueryEnable
+    VkQueryControlFlags                         queryFlags
+    VkQueryPipelineStatisticFlags               pipelineStatistics
+}
+
+class VkCommandBufferBeginInfo {
+    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
+    const void*                                 pNext       /// Pointer to next structure
+    VkCommandBufferUsageFlags                   flags       /// Command buffer usage flags
+    const VkCommandBufferInheritanceInfo*       pInheritanceInfo
+}
+
+class VkRenderPassBeginInfo {
+    VkStructureType                             sType       /// Must be VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
+    const void*                                 pNext       /// Pointer to next structure
+    VkRenderPass                                renderPass
+    VkFramebuffer                               framebuffer
+    VkRect2D                                    renderArea
+    u32                                         clearValueCount
+    const VkClearValue*                         pClearValues
+}
+
+@union
+/// Union allowing specification of floating point, integer, or unsigned integer color data. Actual value selected is based on image/attachment being cleared.
+class VkClearColorValue {
+    f32[4]                                      float32
+    s32[4]                                      int32
+    u32[4]                                      uint32
+}
+
+class VkClearDepthStencilValue {
+    f32                                         depth
+    u32                                         stencil
+}
+
+@union
+/// Union allowing specification of color, depth, and stencil color values. Actual value selected is based on attachment being cleared.
+class VkClearValue {
+    VkClearColorValue                           color
+    VkClearDepthStencilValue                    depthStencil
+}
+
+class VkClearAttachment {
+    VkImageAspectFlags                          aspectMask
+    u32                                         colorAttachment
+    VkClearValue                                clearValue
+}
+
+class VkAttachmentDescription {
+    VkAttachmentDescriptionFlags                flags
+    VkFormat                                    format
+    VkSampleCountFlagBits                       samples
+    VkAttachmentLoadOp                          loadOp          /// Load op for color or depth data
+    VkAttachmentStoreOp                         storeOp         /// Store op for color or depth data
+    VkAttachmentLoadOp                          stencilLoadOp   /// Load op for stencil data
+    VkAttachmentStoreOp                         stencilStoreOp  /// Store op for stencil data
+    VkImageLayout                               initialLayout
+    VkImageLayout                               finalLayout
+}
+
+class VkAttachmentReference {
+    u32                                         attachment
+    VkImageLayout                               layout
+}
+
+class VkSubpassDescription {
+    VkSubpassDescriptionFlags                   flags
+    VkPipelineBindPoint                         pipelineBindPoint  /// Must be VK_PIPELINE_BIND_POINT_GRAPHICS for now
+    u32                                         inputAttachmentCount
+    const VkAttachmentReference*                pInputAttachments
+    u32                                         colorAttachmentCount
+    const VkAttachmentReference*                pColorAttachments
+    const VkAttachmentReference*                pResolveAttachments
+    const VkAttachmentReference*                pDepthStencilAttachment
+    u32                                         preserveAttachmentCount
+    const u32*                                  pPreserveAttachments
+}
+
+class VkSubpassDependency {
+    u32                                         srcSubpass
+    u32                                         dstSubpass
+    VkPipelineStageFlags                        srcStageMask
+    VkPipelineStageFlags                        dstStageMask
+    VkAccessFlags                               srcAccessMask
+    VkAccessFlags                               dstAccessMask
+    VkDependencyFlags                           dependencyFlags
+}
+
+class VkRenderPassCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkRenderPassCreateFlags                     flags
+    u32                                         attachmentCount
+    const VkAttachmentDescription*              pAttachments
+    u32                                         subpassCount
+    const VkSubpassDescription*                 pSubpasses
+    u32                                         dependencyCount
+    const VkSubpassDependency*                  pDependencies
+}
+
+class VkEventCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_EVENT_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkEventCreateFlags                          flags      /// Event creation flags
+}
+
+class VkFenceCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkFenceCreateFlags                          flags      /// Fence creation flags
+}
+
+class VkPhysicalDeviceFeatures {
+    VkBool32                                    robustBufferAccess                        /// out of bounds buffer accesses are well defined
+    VkBool32                                    fullDrawIndexUint32                       /// full 32-bit range of indices for indexed draw calls
+    VkBool32                                    imageCubeArray                            /// image views which are arrays of cube maps
+    VkBool32                                    independentBlend                          /// blending operations are controlled per-attachment
+    VkBool32                                    geometryShader                            /// geometry stage
+    VkBool32                                    tessellationShader                        /// tessellation control and evaluation stage
+    VkBool32                                    sampleRateShading                         /// per-sample shading and interpolation
+    VkBool32                                    dualSrcBlend                              /// blend operations which take two sources
+    VkBool32                                    logicOp                                   /// logic operations
+    VkBool32                                    multiDrawIndirect                         /// multi draw indirect
+    VkBool32                                    drawIndirectFirstInstance
+    VkBool32                                    depthClamp                                /// depth clamping
+    VkBool32                                    depthBiasClamp                            /// depth bias clamping
+    VkBool32                                    fillModeNonSolid                          /// point and wireframe fill modes
+    VkBool32                                    depthBounds                               /// depth bounds test
+    VkBool32                                    wideLines                                 /// lines with width greater than 1
+    VkBool32                                    largePoints                               /// points with size greater than 1
+    VkBool32                                    alphaToOne                                /// The fragment alpha channel can be forced to maximum representable alpha value
+    VkBool32                                    multiViewport
+    VkBool32                                    samplerAnisotropy
+    VkBool32                                    textureCompressionETC2                    /// ETC texture compression formats
+    VkBool32                                    textureCompressionASTC_LDR                /// ASTC LDR texture compression formats
+    VkBool32                                    textureCompressionBC                      /// BC1-7 texture compressed formats
+    VkBool32                                    occlusionQueryPrecise
+    VkBool32                                    pipelineStatisticsQuery                   /// pipeline statistics query
+    VkBool32                                    vertexPipelineStoresAndAtomics
+    VkBool32                                    fragmentStoresAndAtomics
+    VkBool32                                    shaderTessellationAndGeometryPointSize
+    VkBool32                                    shaderImageGatherExtended                 /// texture gather with run-time values and independent offsets
+    VkBool32                                    shaderStorageImageExtendedFormats         /// the extended set of formats can be used for storage images
+    VkBool32                                    shaderStorageImageMultisample             /// multisample images can be used for storage images
+    VkBool32                                    shaderStorageImageReadWithoutFormat
+    VkBool32                                    shaderStorageImageWriteWithoutFormat
+    VkBool32                                    shaderUniformBufferArrayDynamicIndexing   /// arrays of uniform buffers can be accessed with dynamically uniform indices
+    VkBool32                                    shaderSampledImageArrayDynamicIndexing    /// arrays of sampled images can be accessed with dynamically uniform indices
+    VkBool32                                    shaderStorageBufferArrayDynamicIndexing   /// arrays of storage buffers can be accessed with dynamically uniform indices
+    VkBool32                                    shaderStorageImageArrayDynamicIndexing    /// arrays of storage images can be accessed with dynamically uniform indices
+    VkBool32                                    shaderClipDistance                        /// clip distance in shaders
+    VkBool32                                    shaderCullDistance                        /// cull distance in shaders
+    VkBool32                                    shaderFloat64                             /// 64-bit floats (doubles) in shaders
+    VkBool32                                    shaderInt64                               /// 64-bit integers in shaders
+    VkBool32                                    shaderInt16                               /// 16-bit integers in shaders
+    VkBool32                                    shaderResourceResidency                   /// shader can use texture operations that return resource residency information (requires sparseNonResident support)
+    VkBool32                                    shaderResourceMinLod                      /// shader can use texture operations that specify minimum resource LOD
+    VkBool32                                    sparseBinding                             /// Sparse resources support: Resource memory can be managed at opaque page level rather than object level
+    VkBool32                                    sparseResidencyBuffer                     /// Sparse resources support: GPU can access partially resident buffers
+    VkBool32                                    sparseResidencyImage2D                    /// Sparse resources support: GPU can access partially resident 2D (non-MSAA non-DepthStencil) images
+    VkBool32                                    sparseResidencyImage3D                    /// Sparse resources support: GPU can access partially resident 3D images
+    VkBool32                                    sparseResidency2Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 2 samples
+    VkBool32                                    sparseResidency4Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 4 samples
+    VkBool32                                    sparseResidency8Samples                   /// Sparse resources support: GPU can access partially resident MSAA 2D images with 8 samples
+    VkBool32                                    sparseResidency16Samples                  /// Sparse resources support: GPU can access partially resident MSAA 2D images with 16 samples
+    VkBool32                                    sparseResidencyAliased                    /// Sparse resources support: GPU can correctly access data aliased into multiple locations (opt-in)
+    VkBool32                                    variableMultisampleRate
+    VkBool32                                    inheritedQueries
+}
+
+class VkPhysicalDeviceLimits {
+    /// resource maximum sizes
+    u32                                         maxImageDimension1D                       /// max 1D image dimension
+    u32                                         maxImageDimension2D                       /// max 2D image dimension
+    u32                                         maxImageDimension3D                       /// max 3D image dimension
+    u32                                         maxImageDimensionCube                     /// max cubemap image dimension
+    u32                                         maxImageArrayLayers                       /// max layers for image arrays
+    u32                                         maxTexelBufferElements
+    u32                                         maxUniformBufferRange                     /// max uniform buffer size (bytes)
+    u32                                         maxStorageBufferRange                     /// max storage buffer size (bytes)
+    u32                                         maxPushConstantsSize                      /// max size of the push constants pool (bytes)
+    /// memory limits
+    u32                                         maxMemoryAllocationCount                  /// max number of device memory allocations supported
+    u32                                         maxSamplerAllocationCount
+    VkDeviceSize                                bufferImageGranularity                    /// Granularity (in bytes) at which buffers and images can be bound to adjacent memory for simultaneous usage
+    VkDeviceSize                                sparseAddressSpaceSize                    /// Total address space available for sparse allocations (bytes)
+    /// descriptor set limits
+    u32                                         maxBoundDescriptorSets                    /// max number of descriptors sets that can be bound to a pipeline
+    u32                                         maxPerStageDescriptorSamplers             /// max num of samplers allowed per-stage in a descriptor set
+    u32                                         maxPerStageDescriptorUniformBuffers       /// max num of uniform buffers allowed per-stage in a descriptor set
+    u32                                         maxPerStageDescriptorStorageBuffers       /// max num of storage buffers allowed per-stage in a descriptor set
+    u32                                         maxPerStageDescriptorSampledImages        /// max num of sampled images allowed per-stage in a descriptor set
+    u32                                         maxPerStageDescriptorStorageImages        /// max num of storage images allowed per-stage in a descriptor set
+    u32                                         maxPerStageDescriptorInputAttachments
+    u32                                         maxPerStageResources
+    u32                                         maxDescriptorSetSamplers                  /// max num of samplers allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetUniformBuffers            /// max num of uniform buffers allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetUniformBuffersDynamic     /// max num of dynamic uniform buffers allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetStorageBuffers            /// max num of storage buffers allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetStorageBuffersDynamic     /// max num of dynamic storage buffers allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetSampledImages             /// max num of sampled images allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetStorageImages             /// max num of storage images allowed in all stages in a descriptor set
+    u32                                         maxDescriptorSetInputAttachments
+    /// vertex stage limits
+    u32                                         maxVertexInputAttributes                  /// max num of vertex input attribute slots
+    u32                                         maxVertexInputBindings                    /// max num of vertex input binding slots
+    u32                                         maxVertexInputAttributeOffset             /// max vertex input attribute offset added to vertex buffer offset
+    u32                                         maxVertexInputBindingStride               /// max vertex input binding stride
+    u32                                         maxVertexOutputComponents                 /// max num of output components written by vertex shader
+    /// tessellation control stage limits
+    u32                                         maxTessellationGenerationLevel                  /// max level supported by tess primitive generator
+    u32                                         maxTessellationPatchSize                        /// max patch size (vertices)
+    u32                                         maxTessellationControlPerVertexInputComponents  /// max num of input components per-vertex in TCS
+    u32                                         maxTessellationControlPerVertexOutputComponents /// max num of output components per-vertex in TCS
+    u32                                         maxTessellationControlPerPatchOutputComponents  /// max num of output components per-patch in TCS
+    u32                                         maxTessellationControlTotalOutputComponents     /// max total num of per-vertex and per-patch output components in TCS
+    u32                                         maxTessellationEvaluationInputComponents        /// max num of input components per vertex in TES
+    u32                                         maxTessellationEvaluationOutputComponents       /// max num of output components per vertex in TES
+    /// geometry stage limits
+    u32                                         maxGeometryShaderInvocations              /// max invocation count supported in geometry shader
+    u32                                         maxGeometryInputComponents                /// max num of input components read in geometry stage
+    u32                                         maxGeometryOutputComponents               /// max num of output components written in geometry stage
+    u32                                         maxGeometryOutputVertices                 /// max num of vertices that can be emitted in geometry stage
+    u32                                         maxGeometryTotalOutputComponents          /// max total num of components (all vertices) written in geometry stage
+    /// fragment stage limits
+    u32                                         maxFragmentInputComponents                /// max num of input compontents read in fragment stage
+    u32                                         maxFragmentOutputAttachments              /// max num of output attachments written in fragment stage
+    u32                                         maxFragmentDualSrcAttachments             /// max num of output attachments written when using dual source blending
+    u32                                         maxFragmentCombinedOutputResources        /// max total num of storage buffers, storage images and output buffers
+    /// compute stage limits
+    u32                                         maxComputeSharedMemorySize                /// max total storage size of work group local storage (bytes)
+    u32[3]                                      maxComputeWorkGroupCount                  /// max num of compute work groups that may be dispatched by a single command (x,y,z)
+    u32                                         maxComputeWorkGroupInvocations            /// max total compute invocations in a single local work group
+    u32[3]                                      maxComputeWorkGroupSize                   /// max local size of a compute work group (x,y,z)
+
+    u32                                         subPixelPrecisionBits                     /// num bits of subpixel precision in screen x and y
+    u32                                         subTexelPrecisionBits                     /// num bits of subtexel precision
+    u32                                         mipmapPrecisionBits                       /// num bits of mipmap precision
+
+    u32                                         maxDrawIndexedIndexValue                  /// max index value for indexed draw calls (for 32-bit indices)
+    u32                                         maxDrawIndirectCount
+
+    f32                                         maxSamplerLodBias                         /// max absolute sampler level of detail bias
+    f32                                         maxSamplerAnisotropy                      /// max degree of sampler anisotropy
+
+    u32                                         maxViewports                              /// max number of active viewports
+    u32[2]                                      maxViewportDimensions                     /// max viewport dimensions (x,y)
+    f32[2]                                      viewportBoundsRange                       /// viewport bounds range (min,max)
+    u32                                         viewportSubPixelBits                      /// num bits of subpixel precision for viewport
+
+    platform.size_t                             minMemoryMapAlignment                     /// min required alignment of pointers returned by MapMemory (bytes)
+    VkDeviceSize                                minTexelBufferOffsetAlignment             /// min required alignment for texel buffer offsets (bytes)
+    VkDeviceSize                                minUniformBufferOffsetAlignment           /// min required alignment for uniform buffer sizes and offsets (bytes)
+    VkDeviceSize                                minStorageBufferOffsetAlignment           /// min required alignment for storage buffer offsets (bytes)
+
+    s32                                         minTexelOffset                            /// min texel offset for OpTextureSampleOffset
+    u32                                         maxTexelOffset                            /// max texel offset for OpTextureSampleOffset
+    s32                                         minTexelGatherOffset                      /// min texel offset for OpTextureGatherOffset
+    u32                                         maxTexelGatherOffset                      /// max texel offset for OpTextureGatherOffset
+    f32                                         minInterpolationOffset                    /// furthest negative offset for interpolateAtOffset
+    f32                                         maxInterpolationOffset                    /// furthest positive offset for interpolateAtOffset
+    u32                                         subPixelInterpolationOffsetBits           /// num of subpixel bits for interpolateAtOffset
+
+    u32                                         maxFramebufferWidth                       /// max width for a framebuffer
+    u32                                         maxFramebufferHeight                      /// max height for a framebuffer
+    u32                                         maxFramebufferLayers                      /// max layer count for a layered framebuffer
+    VkSampleCountFlags                          framebufferColorSampleCounts
+    VkSampleCountFlags                          framebufferDepthSampleCounts
+    VkSampleCountFlags                          framebufferStencilSampleCounts
+    VkSampleCountFlags                          framebufferNoAttachmentSampleCounts
+    u32                                         maxColorAttachments                       /// max num of framebuffer color attachments
+
+    VkSampleCountFlags                          sampledImageColorSampleCounts
+    VkSampleCountFlags                          sampledImageIntegerSampleCounts
+    VkSampleCountFlags                          sampledImageDepthSampleCounts
+    VkSampleCountFlags                          sampledImageStencilSampleCounts
+    VkSampleCountFlags                          storageImageSampleCounts
+    u32                                         maxSampleMaskWords                        /// max num of sample mask words
+    VkBool32                                    timestampComputeAndGraphics
+
+    f32                                         timestampPeriod
+
+    u32                                         maxClipDistances                          /// max number of clip distances
+    u32                                         maxCullDistances                          /// max number of cull distances
+    u32                                         maxCombinedClipAndCullDistances           /// max combined number of user clipping
+
+    u32                                         discreteQueuePriorities
+
+    f32[2]                                      pointSizeRange                            /// range (min,max) of supported point sizes
+    f32[2]                                      lineWidthRange                            /// range (min,max) of supported line widths
+    f32                                         pointSizeGranularity                      /// granularity of supported point sizes
+    f32                                         lineWidthGranularity                      /// granularity of supported line widths
+    VkBool32                                    strictLines
+    VkBool32                                    standardSampleLocations
+
+    VkDeviceSize                                optimalBufferCopyOffsetAlignment
+    VkDeviceSize                                optimalBufferCopyRowPitchAlignment
+    VkDeviceSize                                nonCoherentAtomSize
+}
+
+class VkPhysicalDeviceSparseProperties {
+    VkBool32                                    residencyStandard2DBlockShape             /// Sparse resources support: GPU will access all 2D (single sample) sparse resources using the standard block shapes (based on pixel format)
+    VkBool32                                    residencyStandard2DMultisampleBlockShape  /// Sparse resources support: GPU will access all 2D (multisample) sparse resources using the standard block shapes (based on pixel format)
+    VkBool32                                    residencyStandard3DBlockShape             /// Sparse resources support: GPU will access all 3D sparse resources using the standard block shapes (based on pixel format)
+    VkBool32                                    residencyAlignedMipSize                   /// Sparse resources support: Images with mip-level dimensions that are NOT a multiple of the block size will be placed in the mip tail
+    VkBool32                                    residencyNonResidentStrict                /// Sparse resources support: GPU can safely access non-resident regions of a resource, all reads return as if data is 0, writes are discarded
+}
+
+class VkSemaphoreCreateInfo {
+    VkStructureType                             sType      /// Must be VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO
+    const void*                                 pNext      /// Pointer to next structure
+    VkSemaphoreCreateFlags                      flags      /// Semaphore creation flags
+}
+
+class VkQueryPoolCreateInfo {
+    VkStructureType                             sType              /// Must be VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO
+    const void*                                 pNext              /// Pointer to next structure
+    VkQueryPoolCreateFlags                      flags
+    VkQueryType                                 queryType
+    u32                                         queryCount
+    VkQueryPipelineStatisticFlags               pipelineStatistics /// Optional
+}
+
+class VkFramebufferCreateInfo {
+    VkStructureType                             sType  /// Must be VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
+    const void*                                 pNext  /// Pointer to next structure
+    VkFramebufferCreateFlags                    flags
+    VkRenderPass                                renderPass
+    u32                                         attachmentCount
+    const VkImageView*                          pAttachments
+    u32                                         width
+    u32                                         height
+    u32                                         layers
+}
+
+class VkDrawIndirectCommand {
+    u32                                         vertexCount
+    u32                                         instanceCount
+    u32                                         firstVertex
+    u32                                         firstInstance
+}
+
+class VkDrawIndexedIndirectCommand {
+    u32                                         indexCount
+    u32                                         instanceCount
+    u32                                         firstIndex
+    s32                                         vertexOffset
+    u32                                         firstInstance
+}
+
+class VkDispatchIndirectCommand {
+    u32                                         x
+    u32                                         y
+    u32                                         z
+}
+
+@extension("VK_KHR_surface")
+class VkSurfaceCapabilitiesKHR {
+    u32                                         minImageCount
+    u32                                         maxImageCount
+    VkExtent2D                                  currentExtent
+    VkExtent2D                                  minImageExtent
+    VkExtent2D                                  maxImageExtent
+    u32                                         maxImageArrayLayers
+    VkSurfaceTransformFlagsKHR                  supportedTransforms
+    VkSurfaceTransformFlagBitsKHR               currentTransform
+    VkCompositeAlphaFlagsKHR                    supportedCompositeAlpha
+    VkImageUsageFlags                           supportedUsageFlags
+}
+
+@extension("VK_KHR_surface")
+class VkSurfaceFormatKHR {
+    VkFormat                                    format
+    VkColorSpaceKHR                             colorSpace
+}
+
+@extension("VK_KHR_swapchain")
+class VkSwapchainCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkSwapchainCreateFlagsKHR                   flags
+    VkSurfaceKHR                                surface
+    u32                                         minImageCount
+    VkFormat                                    imageFormat
+    VkColorSpaceKHR                             imageColorSpace
+    VkExtent2D                                  imageExtent
+    u32                                         imageArrayLayers
+    VkImageUsageFlags                           imageUsage
+    VkSharingMode                               sharingMode
+    u32                                         queueFamilyIndexCount
+    const u32*                                  pQueueFamilyIndices
+    VkSurfaceTransformFlagBitsKHR               preTransform
+    VkCompositeAlphaFlagBitsKHR                 compositeAlpha
+    VkPresentModeKHR                            presentMode
+    VkBool32                                    clipped
+    VkSwapchainKHR                              oldSwapchain
+}
+
+@extension("VK_KHR_swapchain")
+class VkPresentInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    u32                                         waitSemaphoreCount
+    const VkSemaphore*                          pWaitSemaphores
+    u32                                         swapchainCount
+    const VkSwapchainKHR*                       pSwapchains
+    const u32*                                  pImageIndices
+    VkResult*                                   pResults
+}
+
+@extension("VK_KHR_display")
+class VkDisplayPropertiesKHR {
+    VkDisplayKHR                                display
+    const char*                                 displayName
+    VkExtent2D                                  physicalDimensions
+    VkExtent2D                                  physicalResolution
+    VkSurfaceTransformFlagsKHR                  supportedTransforms
+    VkBool32                                    planeReorderPossible
+    VkBool32                                    persistentContent
+}
+
+@extension("VK_KHR_display")
+class VkDisplayModeParametersKHR {
+    VkExtent2D                                  visibleRegion
+    u32                                         refreshRate
+}
+
+@extension("VK_KHR_display")
+class VkDisplayModePropertiesKHR {
+    VkDisplayModeKHR                            displayMode
+    VkDisplayModeParametersKHR                  parameters
+}
+
+@extension("VK_KHR_display")
+class VkDisplayModeCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkDisplayModeCreateFlagsKHR                 flags
+    VkDisplayModeParametersKHR                  parameters
+}
+
+@extension("VK_KHR_display")
+class VkDisplayPlanePropertiesKHR {
+    VkDisplayKHR                                currentDisplay
+    u32                                         currentStackIndex
+}
+
+@extension("VK_KHR_display")
+class VkDisplayPlaneCapabilitiesKHR {
+    VkDisplayPlaneAlphaFlagsKHR                 supportedAlpha
+    VkOffset2D                                  minSrcPosition
+    VkOffset2D                                  maxSrcPosition
+    VkExtent2D                                  minSrcExtent
+    VkExtent2D                                  maxSrcExtent
+    VkOffset2D                                  minDstPosition
+    VkOffset2D                                  maxDstPosition
+    VkExtent2D                                  minDstExtent
+    VkExtent2D                                  maxDstExtent
+}
+
+@extension("VK_KHR_display")
+class VkDisplaySurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkDisplaySurfaceCreateFlagsKHR              flags
+    VkDisplayModeKHR                            displayMode
+    u32                                         planeIndex
+    u32                                         planeStackIndex
+    VkSurfaceTransformFlagBitsKHR               transform
+    f32                                         globalAlpha
+    VkDisplayPlaneAlphaFlagBitsKHR              alphaMode
+    VkExtent2D                                  imageExtent
+}
+
+@extension("VK_KHR_display_swapchain")
+class VkDisplayPresentInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkRect2D                                    srcRect
+    VkRect2D                                    dstRect
+    VkBool32                                    persistent
+}
+
+@extension("VK_KHR_xlib_surface")
+class VkXlibSurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkXlibSurfaceCreateFlagsKHR                 flags
+    platform.Display*                           dpy
+    platform.Window                             window
+}
+
+@extension("VK_KHR_xcb_surface")
+class VkXcbSurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkXcbSurfaceCreateFlagsKHR                  flags
+    platform.xcb_connection_t*                  connection
+    platform.xcb_window_t                       window
+}
+
+@extension("VK_KHR_wayland_surface")
+class VkWaylandSurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkWaylandSurfaceCreateFlagsKHR              flags
+    platform.wl_display*                        display
+    platform.wl_surface*                        surface
+}
+
+@extension("VK_KHR_mir_surface")
+class VkMirSurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkMirSurfaceCreateFlagsKHR                  flags
+    platform.MirConnection*                     connection
+    platform.MirSurface*                        mirSurface
+}
+
+@extension("VK_KHR_android_surface")
+class VkAndroidSurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkAndroidSurfaceCreateFlagsKHR              flags
+    platform.ANativeWindow*                     window
+}
+
+@extension("VK_KHR_win32_surface")
+class VkWin32SurfaceCreateInfoKHR {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkWin32SurfaceCreateFlagsKHR                flags
+    platform.HINSTANCE                          hinstance
+    platform.HWND                               hwnd
+}
+
+@extension("VK_ANDROID_native_buffer")
+class VkNativeBufferANDROID {
+    VkStructureType                             sType
+    const void*                                 pNext
+    platform.buffer_handle_t                    handle
+    int                                         stride
+    int                                         format
+    int                                         usage
+}
+
+@extension("VK_EXT_debug_report")
+class VkDebugReportCallbackCreateInfoEXT {
+    VkStructureType                             sType
+    const void*                                 pNext
+    VkDebugReportFlagsEXT                       flags
+    PFN_vkDebugReportCallbackEXT                pfnCallback
+    void*                                       pUserData
+}
+
+
+////////////////
+//  Commands  //
+////////////////
+
+// Function pointers. TODO: add support for function pointers.
+
+@external type void* PFN_vkVoidFunction
+@pfn cmd void vkVoidFunction() {
+}
+
+@external type void* PFN_vkAllocationFunction
+@pfn cmd void* vkAllocationFunction(
+        void*                                       pUserData,
+        platform.size_t                             size,
+        platform.size_t                             alignment,
+        VkSystemAllocationScope                     allocationScope) {
+    return ?
+}
+
+@external type void* PFN_vkReallocationFunction
+@pfn cmd void* vkReallocationFunction(
+        void*                                       pUserData,
+        void*                                       pOriginal,
+        platform.size_t                             size,
+        platform.size_t                             alignment,
+        VkSystemAllocationScope                     allocationScope) {
+    return ?
+}
+
+@external type void* PFN_vkFreeFunction
+@pfn cmd void vkFreeFunction(
+        void*                                       pUserData,
+        void*                                       pMemory) {
+}
+
+@external type void* PFN_vkInternalAllocationNotification
+@pfn cmd void vkInternalAllocationNotification(
+        void*                                       pUserData,
+        platform.size_t                             size,
+        VkInternalAllocationType                    allocationType,
+        VkSystemAllocationScope                     allocationScope) {
+}
+
+@external type void* PFN_vkInternalFreeNotification
+@pfn cmd void vkInternalFreeNotification(
+        void*                                       pUserData,
+        platform.size_t                             size,
+        VkInternalAllocationType                    allocationType,
+        VkSystemAllocationScope                     allocationScope) {
+}
+
+// Global functions
+
+@threadSafety("system")
+cmd VkResult vkCreateInstance(
+        const VkInstanceCreateInfo*                 pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkInstance*                                 pInstance) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
+
+    instance := ?
+    pInstance[0] = instance
+    State.Instances[instance] = new!InstanceObject()
+
+    layers := pCreateInfo.ppEnabledLayerNames[0:pCreateInfo.enabledLayerCount]
+    extensions := pCreateInfo.ppEnabledExtensionNames[0:pCreateInfo.enabledExtensionCount]
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyInstance(
+        VkInstance                                  instance,
+        const VkAllocationCallbacks*                pAllocator) {
+    instanceObject := GetInstance(instance)
+
+    State.Instances[instance] = null
+}
+
+@threadSafety("system")
+cmd VkResult vkEnumeratePhysicalDevices(
+        VkInstance                                  instance,
+        u32*                                        pPhysicalDeviceCount,
+        VkPhysicalDevice*                           pPhysicalDevices) {
+    instanceObject := GetInstance(instance)
+
+    physicalDeviceCount := as!u32(?)
+    pPhysicalDeviceCount[0] = physicalDeviceCount
+    physicalDevices := pPhysicalDevices[0:physicalDeviceCount]
+
+    for i in (0 .. physicalDeviceCount) {
+        physicalDevice := ?
+        physicalDevices[i] = physicalDevice
+        if !(physicalDevice in State.PhysicalDevices) {
+            State.PhysicalDevices[physicalDevice] = new!PhysicalDeviceObject(instance: instance)
+        }
+    }
+
+    return ?
+}
+
+cmd PFN_vkVoidFunction vkGetDeviceProcAddr(
+        VkDevice                                    device,
+        const char*                                 pName) {
+    if device != NULL_HANDLE {
+        device := GetDevice(device)
+    }
+
+    return ?
+}
+
+cmd PFN_vkVoidFunction vkGetInstanceProcAddr(
+        VkInstance                                  instance,
+        const char*                                 pName) {
+    if instance != NULL_HANDLE {
+        instanceObject := GetInstance(instance)
+    }
+
+    return ?
+}
+
+cmd void vkGetPhysicalDeviceProperties(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceProperties*                 pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    properties := ?
+    pProperties[0] = properties
+}
+
+cmd void vkGetPhysicalDeviceQueueFamilyProperties(
+        VkPhysicalDevice                            physicalDevice,
+        u32*                                        pQueueFamilyPropertyCount,
+        VkQueueFamilyProperties*                    pQueueFamilyProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    // TODO: Figure out how to express fetch-count-or-properties
+    // This version fails 'apic validate' with 'fence not allowed in
+    // *semantic.Branch'. Other attempts have failed with the same or other
+    // errors.
+    // if pQueueFamilyProperties != null {
+    //     queuesProperties := pQueueFamilyProperties[0:pCount[0]]
+    //     for i in (0 .. pCount[0]) {
+    //         queueProperties := as!VkQueueFamilyProperties(?)
+    //         queuesProperties[i] = queueProperties
+    //    }
+    // } else {
+    //     count := ?
+    //     pCount[0] = count
+    // }
+}
+
+cmd void vkGetPhysicalDeviceMemoryProperties(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceMemoryProperties*           pMemoryProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    memoryProperties := ?
+    pMemoryProperties[0] = memoryProperties
+}
+
+cmd void vkGetPhysicalDeviceFeatures(
+        VkPhysicalDevice                            physicalDevice,
+        VkPhysicalDeviceFeatures*                   pFeatures) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    features := ?
+    pFeatures[0] = features
+}
+
+cmd void vkGetPhysicalDeviceFormatProperties(
+        VkPhysicalDevice                            physicalDevice,
+        VkFormat                                    format,
+        VkFormatProperties*                         pFormatProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    formatProperties := ?
+    pFormatProperties[0] = formatProperties
+}
+
+cmd VkResult vkGetPhysicalDeviceImageFormatProperties(
+        VkPhysicalDevice                            physicalDevice,
+        VkFormat                                    format,
+        VkImageType                                 type,
+        VkImageTiling                               tiling,
+        VkImageUsageFlags                           usage,
+        VkImageCreateFlags                          flags,
+        VkImageFormatProperties*                    pImageFormatProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    imageFormatProperties := ?
+    pImageFormatProperties[0] = imageFormatProperties
+
+    return ?
+}
+
+
+// Device functions
+
+@threadSafety("system")
+cmd VkResult vkCreateDevice(
+        VkPhysicalDevice                            physicalDevice,
+        const VkDeviceCreateInfo*                   pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDevice*                                   pDevice) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    device := ?
+    pDevice[0] = device
+    State.Devices[device] = new!DeviceObject(physicalDevice: physicalDevice)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyDevice(
+        VkDevice                                    device,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+
+    State.Devices[device] = null
+}
+
+
+// Extension discovery functions
+
+cmd VkResult vkEnumerateInstanceLayerProperties(
+        u32*                                        pPropertyCount,
+        VkLayerProperties*                          pProperties) {
+    count := as!u32(?)
+    pPropertyCount[0] = count
+
+    properties := pProperties[0:count]
+    for i in (0 .. count) {
+        property := ?
+        properties[i] = property
+    }
+
+    return ?
+}
+
+cmd VkResult vkEnumerateInstanceExtensionProperties(
+        const char*                                 pLayerName,
+        u32*                                        pPropertyCount,
+        VkExtensionProperties*                      pProperties) {
+    count := as!u32(?)
+    pPropertyCount[0] = count
+
+    properties := pProperties[0:count]
+    for i in (0 .. count) {
+        property := ?
+        properties[i] = property
+    }
+
+    return ?
+}
+
+cmd VkResult vkEnumerateDeviceLayerProperties(
+        VkPhysicalDevice                            physicalDevice,
+        u32*                                        pPropertyCount,
+        VkLayerProperties*                          pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    count := as!u32(?)
+    pPropertyCount[0] = count
+
+    properties := pProperties[0:count]
+    for i in (0 .. count) {
+        property := ?
+        properties[i] = property
+    }
+
+    return ?
+}
+
+cmd VkResult vkEnumerateDeviceExtensionProperties(
+        VkPhysicalDevice                            physicalDevice,
+        const char*                                 pLayerName,
+        u32*                                        pPropertyCount,
+        VkExtensionProperties*                      pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    count := as!u32(?)
+    pPropertyCount[0] = count
+
+    properties := pProperties[0:count]
+    for i in (0 .. count) {
+        property := ?
+        properties[i] = property
+    }
+
+    return ?
+}
+
+
+// Queue functions
+
+@threadSafety("system")
+cmd void vkGetDeviceQueue(
+        VkDevice                                    device,
+        u32                                         queueFamilyIndex,
+        u32                                         queueIndex,
+        VkQueue*                                    pQueue) {
+    deviceObject := GetDevice(device)
+
+    queue := ?
+    pQueue[0] = queue
+
+    if !(queue in State.Queues) {
+        State.Queues[queue] = new!QueueObject(device: device)
+    }
+}
+
+@threadSafety("app")
+cmd VkResult vkQueueSubmit(
+        VkQueue                                     queue,
+        u32                                         submitCount,
+        const VkSubmitInfo*                         pSubmits,
+        VkFence                                     fence) {
+    queueObject := GetQueue(queue)
+
+    if fence != NULL_HANDLE {
+        fenceObject := GetFence(fence)
+        assert(fenceObject.device == queueObject.device)
+    }
+
+    // commandBuffers := pcommandBuffers[0:commandBufferCount]
+    // for i in (0 .. commandBufferCount) {
+    //    commandBuffer := commandBuffers[i]
+    //    commandBufferObject := GetCommandBuffer(commandBuffer)
+    //    assert(commandBufferObject.device == queueObject.device)
+    //
+    //    validate("QueueCheck", commandBufferObject.queueFlags in queueObject.flags,
+    //        "vkQueueSubmit: enqueued commandBuffer requires missing queue capabilities.")
+    // }
+
+    return ?
+}
+
+@threadSafety("system")
+cmd VkResult vkQueueWaitIdle(
+        VkQueue                                     queue) {
+    queueObject := GetQueue(queue)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd VkResult vkDeviceWaitIdle(
+        VkDevice                                    device) {
+    deviceObject := GetDevice(device)
+
+    return ?
+}
+
+
+// Memory functions
+
+@threadSafety("system")
+cmd VkResult vkAllocateMemory(
+        VkDevice                                    device,
+        const VkMemoryAllocateInfo*                 pAllocateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDeviceMemory*                             pMemory) {
+    assert(pAllocateInfo.sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO)
+    deviceObject := GetDevice(device)
+
+    memory := ?
+    pMemory[0] = memory
+    State.DeviceMemories[memory] = new!DeviceMemoryObject(
+        device: device,
+        allocationSize: pAllocateInfo[0].allocationSize)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkFreeMemory(
+        VkDevice                                    device,
+        VkDeviceMemory                              memory,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    memoryObject := GetDeviceMemory(memory)
+    assert(memoryObject.device == device)
+
+    // Check that no objects are still bound before freeing.
+    validate("MemoryCheck", len(memoryObject.boundObjects) == 0,
+        "vkFreeMemory: objects still bound")
+    validate("MemoryCheck", len(memoryObject.boundCommandBuffers) == 0,
+        "vkFreeMemory: commandBuffers still bound")
+    State.DeviceMemories[memory] = null
+}
+
+@threadSafety("app")
+cmd VkResult vkMapMemory(
+        VkDevice                                    device,
+        VkDeviceMemory                              memory,
+        VkDeviceSize                                offset,
+        VkDeviceSize                                size,
+        VkMemoryMapFlags                            flags,
+        void**                                      ppData) {
+    deviceObject := GetDevice(device)
+    memoryObject := GetDeviceMemory(memory)
+    assert(memoryObject.device == device)
+
+    assert(flags == as!VkMemoryMapFlags(0))
+    assert((offset + size) <= memoryObject.allocationSize)
+
+    return ?
+}
+
+@threadSafety("app")
+cmd void vkUnmapMemory(
+        VkDevice                                    device,
+        VkDeviceMemory                              memory) {
+    deviceObject := GetDevice(device)
+    memoryObject := GetDeviceMemory(memory)
+    assert(memoryObject.device == device)
+}
+
+cmd VkResult vkFlushMappedMemoryRanges(
+        VkDevice                                    device,
+        u32                                         memoryRangeCount
+        const VkMappedMemoryRange*                  pMemoryRanges) {
+    deviceObject := GetDevice(device)
+
+    memoryRanges := pMemoryRanges[0:memoryRangeCount]
+    for i in (0 .. memoryRangeCount) {
+        memoryRange := memoryRanges[i]
+        memoryObject := GetDeviceMemory(memoryRange.memory)
+        assert(memoryObject.device == device)
+        assert((memoryRange.offset + memoryRange.size) <= memoryObject.allocationSize)
+    }
+
+    return ?
+}
+
+cmd VkResult vkInvalidateMappedMemoryRanges(
+        VkDevice                                    device,
+        u32                                         memoryRangeCount,
+        const VkMappedMemoryRange*                  pMemoryRanges) {
+    deviceObject := GetDevice(device)
+
+    memoryRanges := pMemoryRanges[0:memoryRangeCount]
+    for i in (0 .. memoryRangeCount) {
+        memoryRange := memoryRanges[i]
+        memoryObject := GetDeviceMemory(memoryRange.memory)
+        assert(memoryObject.device == device)
+        assert((memoryRange.offset + memoryRange.size) <= memoryObject.allocationSize)
+    }
+
+    return ?
+}
+
+
+// Memory management API functions
+
+cmd void vkGetDeviceMemoryCommitment(
+        VkDevice                                    device,
+        VkDeviceMemory                              memory,
+        VkDeviceSize*                               pCommittedMemoryInBytes) {
+    deviceObject := GetDevice(device)
+
+    if memory != NULL_HANDLE {
+        memoryObject := GetDeviceMemory(memory)
+        assert(memoryObject.device == device)
+    }
+
+    committedMemoryInBytes := ?
+    pCommittedMemoryInBytes[0] = committedMemoryInBytes
+}
+
+cmd void vkGetBufferMemoryRequirements(
+        VkDevice                                    device,
+        VkBuffer                                    buffer,
+        VkMemoryRequirements*                       pMemoryRequirements) {
+    deviceObject := GetDevice(device)
+    bufferObject := GetBuffer(buffer)
+    assert(bufferObject.device == device)
+}
+
+cmd VkResult vkBindBufferMemory(
+        VkDevice                                    device,
+        VkBuffer                                    buffer,
+        VkDeviceMemory                              memory,
+        VkDeviceSize                                memoryOffset) {
+    deviceObject := GetDevice(device)
+    bufferObject := GetBuffer(buffer)
+    assert(bufferObject.device == device)
+
+    // Unbind buffer from previous memory object, if not VK_NULL_HANDLE.
+    if bufferObject.memory != NULL_HANDLE {
+        memoryObject := GetDeviceMemory(bufferObject.memory)
+        memoryObject.boundObjects[as!u64(buffer)] = null
+    }
+
+    // Bind buffer to given memory object, if not VK_NULL_HANDLE.
+    if memory != NULL_HANDLE {
+        memoryObject := GetDeviceMemory(memory)
+        assert(memoryObject.device == device)
+        memoryObject.boundObjects[as!u64(buffer)] = memoryOffset
+    }
+    bufferObject.memory = memory
+    bufferObject.memoryOffset = memoryOffset
+
+    return ?
+}
+
+cmd void vkGetImageMemoryRequirements(
+        VkDevice                                    device,
+        VkImage                                     image,
+        VkMemoryRequirements*                       pMemoryRequirements) {
+    deviceObject := GetDevice(device)
+    imageObject := GetImage(image)
+    assert(imageObject.device == device)
+}
+
+cmd VkResult vkBindImageMemory(
+        VkDevice                                    device,
+        VkImage                                     image,
+        VkDeviceMemory                              memory,
+        VkDeviceSize                                memoryOffset) {
+    deviceObject := GetDevice(device)
+    imageObject := GetImage(image)
+    assert(imageObject.device == device)
+
+    // Unbind image from previous memory object, if not VK_NULL_HANDLE.
+    if imageObject.memory != NULL_HANDLE {
+        memoryObject := GetDeviceMemory(imageObject.memory)
+        memoryObject.boundObjects[as!u64(image)] = null
+    }
+
+    // Bind image to given memory object, if not VK_NULL_HANDLE.
+    if memory != NULL_HANDLE {
+        memoryObject := GetDeviceMemory(memory)
+        assert(memoryObject.device == device)
+        memoryObject.boundObjects[as!u64(image)] = memoryOffset
+    }
+    imageObject.memory = memory
+    imageObject.memoryOffset = memoryOffset
+
+    return ?
+}
+
+cmd void vkGetImageSparseMemoryRequirements(
+        VkDevice                                    device,
+        VkImage                                     image,
+        u32*                                        pSparseMemoryRequirementCount,
+        VkSparseImageMemoryRequirements*            pSparseMemoryRequirements) {
+    deviceObject := GetDevice(device)
+    imageObject := GetImage(image)
+    assert(imageObject.device == device)
+}
+
+cmd void vkGetPhysicalDeviceSparseImageFormatProperties(
+        VkPhysicalDevice                            physicalDevice,
+        VkFormat                                    format,
+        VkImageType                                 type,
+        VkSampleCountFlagBits                       samples,
+        VkImageUsageFlags                           usage,
+        VkImageTiling                               tiling,
+        u32*                                        pPropertyCount,
+        VkSparseImageFormatProperties*              pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+}
+
+cmd VkResult vkQueueBindSparse(
+        VkQueue                                     queue,
+        u32                                         bindInfoCount,
+        const VkBindSparseInfo*                     pBindInfo,
+        VkFence                                     fence) {
+    queueObject := GetQueue(queue)
+
+    return ?
+}
+
+
+// Fence functions
+
+@threadSafety("system")
+cmd VkResult vkCreateFence(
+        VkDevice                                    device,
+        const VkFenceCreateInfo*                    pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkFence*                                    pFence) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_FENCE_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    fence := ?
+    pFence[0] = fence
+    State.Fences[fence] = new!FenceObject(
+        device: device, signaled: (pCreateInfo.flags == as!VkFenceCreateFlags(VK_FENCE_CREATE_SIGNALED_BIT)))
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyFence(
+        VkDevice                                    device,
+        VkFence                                     fence,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    fenceObject := GetFence(fence)
+    assert(fenceObject.device == device)
+
+    State.Fences[fence] = null
+}
+
+@threadSafety("system")
+cmd VkResult vkResetFences(
+        VkDevice                                    device,
+        u32                                         fenceCount,
+        const VkFence*                              pFences) {
+    deviceObject := GetDevice(device)
+
+    fences := pFences[0:fenceCount]
+    for i in (0 .. fenceCount) {
+        fence := fences[i]
+        fenceObject := GetFence(fence)
+        assert(fenceObject.device == device)
+        fenceObject.signaled = false
+    }
+
+    return ?
+}
+
+@threadSafety("system")
+cmd VkResult vkGetFenceStatus(
+        VkDevice                                    device,
+        VkFence                                     fence) {
+    deviceObject := GetDevice(device)
+    fenceObject := GetFence(fence)
+    assert(fenceObject.device == device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd VkResult vkWaitForFences(
+        VkDevice                                    device,
+        u32                                         fenceCount,
+        const VkFence*                              pFences,
+        VkBool32                                    waitAll,
+        u64                                         timeout) {  /// timeout in nanoseconds
+    deviceObject := GetDevice(device)
+
+    fences := pFences[0:fenceCount]
+    for i in (0 .. fenceCount) {
+        fence := fences[i]
+        fenceObject := GetFence(fence)
+        assert(fenceObject.device == device)
+    }
+
+    return ?
+}
+
+
+// Queue semaphore functions
+
+@threadSafety("system")
+cmd VkResult vkCreateSemaphore(
+        VkDevice                                    device,
+        const VkSemaphoreCreateInfo*                pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkSemaphore*                                pSemaphore) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    semaphore := ?
+    pSemaphore[0] = semaphore
+    State.Semaphores[semaphore] = new!SemaphoreObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroySemaphore(
+        VkDevice                                    device,
+        VkSemaphore                                 semaphore,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    semaphoreObject := GetSemaphore(semaphore)
+    assert(semaphoreObject.device == device)
+
+    State.Semaphores[semaphore] = null
+}
+
+
+// Event functions
+
+@threadSafety("system")
+cmd VkResult vkCreateEvent(
+        VkDevice                                    device,
+        const VkEventCreateInfo*                    pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkEvent*                                    pEvent) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_EVENT_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    event := ?
+    pEvent[0] = event
+    State.Events[event] = new!EventObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyEvent(
+        VkDevice                                    device,
+        VkEvent                                     event,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    eventObject := GetEvent(event)
+    assert(eventObject.device == device)
+
+    State.Events[event] = null
+}
+
+@threadSafety("system")
+cmd VkResult vkGetEventStatus(
+        VkDevice                                    device,
+        VkEvent                                     event) {
+    deviceObject := GetDevice(device)
+    eventObject := GetEvent(event)
+    assert(eventObject.device == device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd VkResult vkSetEvent(
+        VkDevice                                    device,
+        VkEvent                                     event) {
+    deviceObject := GetDevice(device)
+    eventObject := GetEvent(event)
+    assert(eventObject.device == device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd VkResult vkResetEvent(
+        VkDevice                                    device,
+        VkEvent                                     event) {
+    deviceObject := GetDevice(device)
+    eventObject := GetEvent(event)
+    assert(eventObject.device == device)
+
+    return ?
+}
+
+
+// Query functions
+
+@threadSafety("system")
+cmd VkResult vkCreateQueryPool(
+        VkDevice                                    device,
+        const VkQueryPoolCreateInfo*                pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkQueryPool*                                pQueryPool) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    queryPool := ?
+    pQueryPool[0] = queryPool
+    State.QueryPools[queryPool] = new!QueryPoolObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyQueryPool(
+        VkDevice                                    device,
+        VkQueryPool                                 queryPool,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    queryPoolObject := GetQueryPool(queryPool)
+    assert(queryPoolObject.device == device)
+
+    State.QueryPools[queryPool] = null
+}
+
+@threadSafety("system")
+cmd VkResult vkGetQueryPoolResults(
+        VkDevice                                    device,
+        VkQueryPool                                 queryPool,
+        u32                                         firstQuery,
+        u32                                         queryCount,
+        platform.size_t                             dataSize,
+        void*                                       pData,
+        VkDeviceSize                                stride,
+        VkQueryResultFlags                          flags) {
+    deviceObject := GetDevice(device)
+    queryPoolObject := GetQueryPool(queryPool)
+    assert(queryPoolObject.device == device)
+
+    data := pData[0:dataSize]
+
+    return ?
+}
+
+// Buffer functions
+
+@threadSafety("system")
+cmd VkResult vkCreateBuffer(
+        VkDevice                                    device,
+        const VkBufferCreateInfo*                   pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkBuffer*                                   pBuffer) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    buffer := ?
+    pBuffer[0] = buffer
+    State.Buffers[buffer] = new!BufferObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyBuffer(
+        VkDevice                                    device,
+        VkBuffer                                    buffer,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    bufferObject := GetBuffer(buffer)
+    assert(bufferObject.device == device)
+
+    assert(bufferObject.memory == 0)
+    State.Buffers[buffer] = null
+}
+
+
+// Buffer view functions
+
+@threadSafety("system")
+cmd VkResult vkCreateBufferView(
+        VkDevice                                    device,
+        const VkBufferViewCreateInfo*               pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkBufferView*                               pView) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    bufferObject := GetBuffer(pCreateInfo.buffer)
+    assert(bufferObject.device == device)
+
+    view := ?
+    pView[0] = view
+    State.BufferViews[view] = new!BufferViewObject(device: device, buffer: pCreateInfo.buffer)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyBufferView(
+        VkDevice                                    device,
+        VkBufferView                                bufferView,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    bufferViewObject := GetBufferView(bufferView)
+    assert(bufferViewObject.device == device)
+
+    State.BufferViews[bufferView] = null
+}
+
+
+// Image functions
+
+@threadSafety("system")
+cmd VkResult vkCreateImage(
+        VkDevice                                    device,
+        const VkImageCreateInfo*                    pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkImage*                                    pImage) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    image := ?
+    pImage[0] = image
+    State.Images[image] = new!ImageObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyImage(
+        VkDevice                                    device,
+        VkImage                                     image,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    imageObject := GetImage(image)
+    assert(imageObject.device == device)
+
+    assert(imageObject.memory == 0)
+    State.Images[image] = null
+}
+
+cmd void vkGetImageSubresourceLayout(
+        VkDevice                                    device,
+        VkImage                                     image,
+        const VkImageSubresource*                   pSubresource,
+        VkSubresourceLayout*                        pLayout) {
+    deviceObject := GetDevice(device)
+    imageObject := GetImage(image)
+    assert(imageObject.device == device)
+}
+
+
+// Image view functions
+
+@threadSafety("system")
+cmd VkResult vkCreateImageView(
+        VkDevice                                    device,
+        const VkImageViewCreateInfo*                pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkImageView*                                pView) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    imageObject := GetImage(pCreateInfo.image)
+    assert(imageObject.device == device)
+
+    view := ?
+    pView[0] = view
+    State.ImageViews[view] = new!ImageViewObject(device: device, image: pCreateInfo.image)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyImageView(
+        VkDevice                                    device,
+        VkImageView                                 imageView,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    imageViewObject := GetImageView(imageView)
+    assert(imageViewObject.device == device)
+
+    State.ImageViews[imageView] = null
+}
+
+
+// Shader functions
+
+cmd VkResult vkCreateShaderModule(
+        VkDevice                                    device,
+        const VkShaderModuleCreateInfo*             pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkShaderModule*                             pShaderModule) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    shaderModule := ?
+    pShaderModule[0] = shaderModule
+    State.ShaderModules[shaderModule] = new!ShaderModuleObject(device: device)
+
+    return ?
+}
+
+cmd void vkDestroyShaderModule(
+        VkDevice                                    device,
+        VkShaderModule                              shaderModule,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    shaderModuleObject := GetShaderModule(shaderModule)
+    assert(shaderModuleObject.device == device)
+
+    State.ShaderModules[shaderModule] = null
+}
+
+
+// Pipeline functions
+
+cmd VkResult vkCreatePipelineCache(
+        VkDevice                                    device,
+        const VkPipelineCacheCreateInfo*            pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkPipelineCache*                            pPipelineCache) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    pipelineCache := ?
+    pPipelineCache[0] = pipelineCache
+    State.PipelineCaches[pipelineCache] = new!PipelineCacheObject(device: device)
+
+    return ?
+}
+
+cmd void vkDestroyPipelineCache(
+        VkDevice                                    device,
+        VkPipelineCache                             pipelineCache,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    pipelineCacheObject := GetPipelineCache(pipelineCache)
+    assert(pipelineCacheObject.device == device)
+
+    State.PipelineCaches[pipelineCache] = null
+}
+
+cmd VkResult vkGetPipelineCacheData(
+        VkDevice                                    device,
+        VkPipelineCache                             pipelineCache,
+        platform.size_t*                            pDataSize,
+        void*                                       pData) {
+    deviceObject := GetDevice(device)
+    pipelineCacheObject := GetPipelineCache(pipelineCache)
+    assert(pipelineCacheObject.device == device)
+
+    return ?
+}
+
+cmd VkResult vkMergePipelineCaches(
+        VkDevice                                    device,
+        VkPipelineCache                             dstCache,
+        u32                                         srcCacheCount,
+        const VkPipelineCache*                      pSrcCaches) {
+    deviceObject := GetDevice(device)
+    dstCacheObject := GetPipelineCache(dstCache)
+    assert(dstCacheObject.device == device)
+
+    srcCaches := pSrcCaches[0:srcCacheCount]
+    for i in (0 .. srcCacheCount) {
+        srcCache := srcCaches[i]
+        srcCacheObject := GetPipelineCache(srcCache)
+        assert(srcCacheObject.device == device)
+    }
+
+    return ?
+}
+
+cmd VkResult vkCreateGraphicsPipelines(
+        VkDevice                                    device,
+        VkPipelineCache                             pipelineCache,
+        u32                                         createInfoCount,
+        const VkGraphicsPipelineCreateInfo*         pCreateInfos,
+        const VkAllocationCallbacks*                pAllocator,
+        VkPipeline*                                 pPipelines) {
+    deviceObject := GetDevice(device)
+    if pipelineCache != NULL_HANDLE {
+        pipelineCacheObject := GetPipelineCache(pipelineCache)
+        assert(pipelineCacheObject.device == device)
+    }
+
+    createInfos := pCreateInfos[0:createInfoCount]
+    pipelines := pPipelines[0:createInfoCount]
+    for i in (0 .. createInfoCount) {
+        pipeline := ?
+        pipelines[i] = pipeline
+        State.Pipelines[pipeline] = new!PipelineObject(device: device)
+    }
+
+    return ?
+}
+
+cmd VkResult vkCreateComputePipelines(
+        VkDevice                                    device,
+        VkPipelineCache                             pipelineCache,
+        u32                                         createInfoCount,
+        const VkComputePipelineCreateInfo*          pCreateInfos,
+        const VkAllocationCallbacks*                pAllocator,
+        VkPipeline*                                 pPipelines) {
+    deviceObject := GetDevice(device)
+    if pipelineCache != NULL_HANDLE {
+        pipelineCacheObject := GetPipelineCache(pipelineCache)
+        assert(pipelineCacheObject.device == device)
+    }
+
+    createInfos := pCreateInfos[0:createInfoCount]
+    pipelines := pPipelines[0:createInfoCount]
+    for i in (0 .. createInfoCount) {
+        pipeline := ?
+        pipelines[i] = pipeline
+        State.Pipelines[pipeline] = new!PipelineObject(device: device)
+    }
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyPipeline(
+        VkDevice                                    device,
+        VkPipeline                                  pipeline,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    pipelineObjects := GetPipeline(pipeline)
+    assert(pipelineObjects.device == device)
+
+    State.Pipelines[pipeline] = null
+}
+
+
+// Pipeline layout functions
+
+@threadSafety("system")
+cmd VkResult vkCreatePipelineLayout(
+        VkDevice                                    device,
+        const VkPipelineLayoutCreateInfo*           pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkPipelineLayout*                           pPipelineLayout) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    pipelineLayout := ?
+    pPipelineLayout[0] = pipelineLayout
+    State.PipelineLayouts[pipelineLayout] = new!PipelineLayoutObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyPipelineLayout(
+        VkDevice                                    device,
+        VkPipelineLayout                            pipelineLayout,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    pipelineLayoutObjects := GetPipelineLayout(pipelineLayout)
+    assert(pipelineLayoutObjects.device == device)
+
+    State.PipelineLayouts[pipelineLayout] = null
+}
+
+
+// Sampler functions
+
+@threadSafety("system")
+cmd VkResult vkCreateSampler(
+        VkDevice                                    device,
+        const VkSamplerCreateInfo*                  pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkSampler*                                  pSampler) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    sampler := ?
+    pSampler[0] = sampler
+    State.Samplers[sampler] = new!SamplerObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroySampler(
+        VkDevice                                    device,
+        VkSampler                                   sampler,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    samplerObject := GetSampler(sampler)
+    assert(samplerObject.device == device)
+
+    State.Samplers[sampler] = null
+}
+
+
+// Descriptor set functions
+
+@threadSafety("system")
+cmd VkResult vkCreateDescriptorSetLayout(
+        VkDevice                                    device,
+        const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDescriptorSetLayout*                      pSetLayout) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    setLayout := ?
+    pSetLayout[0] = setLayout
+    State.DescriptorSetLayouts[setLayout] = new!DescriptorSetLayoutObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyDescriptorSetLayout(
+        VkDevice                                    device,
+        VkDescriptorSetLayout                       descriptorSetLayout,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    descriptorSetLayoutObject := GetDescriptorSetLayout(descriptorSetLayout)
+    assert(descriptorSetLayoutObject.device == device)
+
+    State.DescriptorSetLayouts[descriptorSetLayout] = null
+}
+
+@threadSafety("system")
+cmd VkResult vkCreateDescriptorPool(
+        VkDevice                                    device,
+        const VkDescriptorPoolCreateInfo*           pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDescriptorPool*                           pDescriptorPool) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    descriptorPool := ?
+    pDescriptorPool[0] = descriptorPool
+    State.DescriptorPools[descriptorPool] = new!DescriptorPoolObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyDescriptorPool(
+        VkDevice                                    device,
+        VkDescriptorPool                            descriptorPool,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    descriptorPoolObject := GetDescriptorPool(descriptorPool)
+    assert(descriptorPoolObject.device == device)
+
+    State.DescriptorPools[descriptorPool] = null
+}
+
+@threadSafety("app")
+cmd VkResult vkResetDescriptorPool(
+        VkDevice                                    device,
+        VkDescriptorPool                            descriptorPool,
+        VkDescriptorPoolResetFlags                  flags) {
+    deviceObject := GetDevice(device)
+    descriptorPoolObject := GetDescriptorPool(descriptorPool)
+    assert(descriptorPoolObject.device == device)
+
+    return ?
+}
+
+@threadSafety("app")
+cmd VkResult vkAllocateDescriptorSets(
+        VkDevice                                    device,
+        const VkDescriptorSetAllocateInfo*          pAllocateInfo,
+        VkDescriptorSet*                            pDescriptorSets) {
+    deviceObject := GetDevice(device)
+    allocInfo := pAllocateInfo[0]
+    descriptorPoolObject := GetDescriptorPool(allocInfo.descriptorPool)
+
+    setLayouts := allocInfo.pSetLayouts[0:allocInfo.setCount]
+    for i in (0 .. allocInfo.setCount) {
+        setLayout := setLayouts[i]
+        setLayoutObject := GetDescriptorSetLayout(setLayout)
+        assert(setLayoutObject.device == device)
+    }
+
+    descriptorSets := pDescriptorSets[0:allocInfo.setCount]
+    for i in (0 .. allocInfo.setCount) {
+        descriptorSet := ?
+        descriptorSets[i] = descriptorSet
+        State.DescriptorSets[descriptorSet] = new!DescriptorSetObject(device: device)
+    }
+
+    return ?
+}
+
+cmd VkResult vkFreeDescriptorSets(
+        VkDevice                                    device,
+        VkDescriptorPool                            descriptorPool,
+        u32                                         descriptorSetCount,
+        const VkDescriptorSet*                      pDescriptorSets) {
+    deviceObject := GetDevice(device)
+    descriptorPoolObject := GetDescriptorPool(descriptorPool)
+
+    descriptorSets := pDescriptorSets[0:descriptorSetCount]
+    for i in (0 .. descriptorSetCount) {
+        descriptorSet := descriptorSets[i]
+        descriptorSetObject := GetDescriptorSet(descriptorSet)
+        assert(descriptorSetObject.device == device)
+        State.DescriptorSets[descriptorSet] = null
+    }
+
+    return ?
+}
+
+cmd void vkUpdateDescriptorSets(
+        VkDevice                                    device,
+        u32                                         descriptorWriteCount,
+        const VkWriteDescriptorSet*                 pDescriptorWrites,
+        u32                                         descriptorCopyCount,
+        const VkCopyDescriptorSet*                  pDescriptorCopies) {
+    deviceObject := GetDevice(device)
+
+    descriptorWrites := pDescriptorWrites[0:descriptorWriteCount]
+    for i in (0 .. descriptorWriteCount) {
+        descriptorWrite := descriptorWrites[i]
+        descriptorWriteObject := GetDescriptorSet(descriptorWrite.dstSet)
+        assert(descriptorWriteObject.device == device)
+    }
+
+    descriptorCopies := pDescriptorCopies[0:descriptorCopyCount]
+    for i in (0 .. descriptorCopyCount) {
+        descriptorCopy := descriptorCopies[i]
+        descriptorCopyObject := GetDescriptorSet(descriptorCopy.dstSet)
+        assert(descriptorCopyObject.device == device)
+    }
+}
+
+
+// Framebuffer functions
+
+@threadSafety("system")
+cmd VkResult vkCreateFramebuffer(
+        VkDevice                                    device,
+        const VkFramebufferCreateInfo*              pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkFramebuffer*                              pFramebuffer) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    framebuffer := ?
+    pFramebuffer[0] = framebuffer
+    State.Framebuffers[framebuffer] = new!FramebufferObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyFramebuffer(
+        VkDevice                                    device,
+        VkFramebuffer                               framebuffer,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    framebufferObject := GetFramebuffer(framebuffer)
+    assert(framebufferObject.device == device)
+
+    State.Framebuffers[framebuffer] = null
+}
+
+
+// Renderpass functions
+
+@threadSafety("system")
+cmd VkResult vkCreateRenderPass(
+        VkDevice                                    device,
+        const VkRenderPassCreateInfo*               pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkRenderPass*                               pRenderPass) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    renderpass := ?
+    pRenderPass[0] = renderpass
+    State.RenderPasses[renderpass] = new!RenderPassObject(device: device)
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkDestroyRenderPass(
+        VkDevice                                    device,
+        VkRenderPass                                renderPass,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    renderPassObject := GetRenderPass(renderPass)
+    assert(renderPassObject.device == device)
+
+    State.RenderPasses[renderPass] = null
+}
+
+cmd void vkGetRenderAreaGranularity(
+        VkDevice                                    device,
+        VkRenderPass                                renderPass,
+        VkExtent2D*                                 pGranularity) {
+    deviceObject := GetDevice(device)
+    renderPassObject := GetRenderPass(renderPass)
+
+    granularity := ?
+    pGranularity[0] = granularity
+}
+
+// Command pool functions
+
+cmd VkResult vkCreateCommandPool(
+        VkDevice                                    device,
+        const VkCommandPoolCreateInfo*              pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkCommandPool*                              pCommandPool) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO)
+    deviceObject := GetDevice(device)
+
+    commandPool := ?
+    pCommandPool[0] = commandPool
+    State.CommandPools[commandPool] = new!CommandPoolObject(device: device)
+
+    return ?
+}
+
+cmd void vkDestroyCommandPool(
+        VkDevice                                    device,
+        VkCommandPool                               commandPool,
+        const VkAllocationCallbacks*                pAllocator) {
+    deviceObject := GetDevice(device)
+    commandPoolObject := GetCommandPool(commandPool)
+    assert(commandPoolObject.device == device)
+
+    State.CommandPools[commandPool] = null
+}
+
+cmd VkResult vkResetCommandPool(
+        VkDevice                                    device,
+        VkCommandPool                               commandPool,
+        VkCommandPoolResetFlags                     flags) {
+    deviceObject := GetDevice(device)
+    commandPoolObject := GetCommandPool(commandPool)
+    assert(commandPoolObject.device == device)
+
+    return ?
+}
+
+// Command buffer functions
+
+macro void bindCommandBuffer(VkCommandBuffer commandBuffer, any obj, VkDeviceMemory memory) {
+    memoryObject := GetDeviceMemory(memory)
+    memoryObject.boundCommandBuffers[commandBuffer] = commandBuffer
+
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.boundObjects[as!u64(obj)] = memory
+}
+
+macro void unbindCommandBuffer(VkCommandBuffer commandBuffer, any obj, VkDeviceMemory memory) {
+    memoryObject := GetDeviceMemory(memory)
+    memoryObject.boundCommandBuffers[commandBuffer] = null
+
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.boundObjects[as!u64(obj)] = null
+}
+
+@threadSafety("system")
+cmd VkResult vkAllocateCommandBuffers(
+        VkDevice                                    device,
+        const VkCommandBufferAllocateInfo*          pAllocateInfo,
+        VkCommandBuffer*                            pCommandBuffers) {
+    assert(pAllocateInfo[0].sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO)
+
+    count := pAllocateInfo[0].commandBufferCount
+    commandBuffers := pCommandBuffers[0:count]
+    for i in (0 .. count) {
+        commandBuffer := ?
+        commandBuffers[i] = commandBuffer
+        State.CommandBuffers[commandBuffer] = new!CommandBufferObject(device: device)
+    }
+
+    return ?
+}
+
+@threadSafety("system")
+cmd void vkFreeCommandBuffers(
+        VkDevice                                    device,
+        VkCommandPool                               commandPool,
+        u32                                         commandBufferCount,
+        const VkCommandBuffer*                      pCommandBuffers) {
+    deviceObject := GetDevice(device)
+
+    commandBuffers := pCommandBuffers[0:commandBufferCount]
+    for i in (0 .. commandBufferCount) {
+        commandBufferObject := GetCommandBuffer(commandBuffers[i])
+        assert(commandBufferObject.device == device)
+        // TODO: iterate over boundObjects and clear memory bindings
+        State.CommandBuffers[commandBuffers[i]] = null
+    }
+}
+
+@threadSafety("app")
+cmd VkResult vkBeginCommandBuffer(
+        VkCommandBuffer                             commandBuffer,
+        const VkCommandBufferBeginInfo*             pBeginInfo) {
+    assert(pBeginInfo.sType == VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO)
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    // TODO: iterate over boundObjects and clear memory bindings
+
+    return ?
+}
+
+@threadSafety("app")
+cmd VkResult vkEndCommandBuffer(
+        VkCommandBuffer                             commandBuffer) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    return ?
+}
+
+@threadSafety("app")
+cmd VkResult vkResetCommandBuffer(
+        VkCommandBuffer                             commandBuffer,
+        VkCommandBufferResetFlags                   flags) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    // TODO: iterate over boundObjects and clear memory bindings
+
+    return ?
+}
+
+
+// Command buffer building functions
+
+@threadSafety("app")
+cmd void vkCmdBindPipeline(
+        VkCommandBuffer                             commandBuffer,
+        VkPipelineBindPoint                         pipelineBindPoint,
+        VkPipeline                                  pipeline) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    pipelineObject := GetPipeline(pipeline)
+    assert(commandBufferObject.device == pipelineObject.device)
+
+    queue := switch (pipelineBindPoint) {
+        case VK_PIPELINE_BIND_POINT_COMPUTE:  VK_QUEUE_COMPUTE_BIT
+        case VK_PIPELINE_BIND_POINT_GRAPHICS: VK_QUEUE_GRAPHICS_BIT
+    }
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, queue)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetViewport(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         firstViewport,
+        u32                                         viewportCount,
+        const VkViewport*                           pViewports) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetScissor(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         firstScissor,
+        u32                                         scissorCount,
+        const VkRect2D*                             pScissors) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetLineWidth(
+        VkCommandBuffer                             commandBuffer,
+        f32                                         lineWidth) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetDepthBias(
+        VkCommandBuffer                             commandBuffer,
+        f32                                         depthBiasConstantFactor,
+        f32                                         depthBiasClamp,
+        f32                                         depthBiasSlopeFactor) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetBlendConstants(
+        VkCommandBuffer                             commandBuffer,
+        // TODO(jessehall): apic only supports 'const' on pointer types. Using
+        // an annotation as a quick hack to pass this to the template without
+        // having to modify the AST and semantic model.
+        @readonly f32[4]                            blendConstants) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetDepthBounds(
+        VkCommandBuffer                             commandBuffer,
+        f32                                         minDepthBounds,
+        f32                                         maxDepthBounds) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetStencilCompareMask(
+        VkCommandBuffer                             commandBuffer,
+        VkStencilFaceFlags                          faceMask,
+        u32                                         compareMask) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetStencilWriteMask(
+        VkCommandBuffer                             commandBuffer,
+        VkStencilFaceFlags                          faceMask,
+        u32                                         writeMask) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetStencilReference(
+        VkCommandBuffer                             commandBuffer,
+        VkStencilFaceFlags                          faceMask,
+        u32                                         reference) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdBindDescriptorSets(
+        VkCommandBuffer                             commandBuffer,
+        VkPipelineBindPoint                         pipelineBindPoint,
+        VkPipelineLayout                            layout,
+        u32                                         firstSet,
+        u32                                         descriptorSetCount,
+        const VkDescriptorSet*                      pDescriptorSets,
+        u32                                         dynamicOffsetCount,
+        const u32*                                  pDynamicOffsets) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    descriptorSets := pDescriptorSets[0:descriptorSetCount]
+    for i in (0 .. descriptorSetCount) {
+        descriptorSet := descriptorSets[i]
+        descriptorSetObject := GetDescriptorSet(descriptorSet)
+        assert(commandBufferObject.device == descriptorSetObject.device)
+    }
+
+    dynamicOffsets := pDynamicOffsets[0:dynamicOffsetCount]
+    for i in (0 .. dynamicOffsetCount) {
+        dynamicOffset := dynamicOffsets[i]
+    }
+
+    queue := switch (pipelineBindPoint) {
+        case VK_PIPELINE_BIND_POINT_COMPUTE:  VK_QUEUE_COMPUTE_BIT
+        case VK_PIPELINE_BIND_POINT_GRAPHICS: VK_QUEUE_GRAPHICS_BIT
+    }
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, queue)
+}
+
+@threadSafety("app")
+cmd void vkCmdBindIndexBuffer(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        VkIndexType                                 indexType) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    bufferObject := GetBuffer(buffer)
+    assert(commandBufferObject.device == bufferObject.device)
+
+    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdBindVertexBuffers(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         firstBinding,
+        u32                                         bindingCount,
+        const VkBuffer*                             pBuffers,
+        const VkDeviceSize*                         pOffsets) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    // TODO: check if not [firstBinding:firstBinding+bindingCount]
+    buffers := pBuffers[0:bindingCount]
+    offsets := pOffsets[0:bindingCount]
+    for i in (0 .. bindingCount) {
+        buffer := buffers[i]
+        offset := offsets[i]
+        bufferObject := GetBuffer(buffer)
+        assert(commandBufferObject.device == bufferObject.device)
+
+        bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
+    }
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdDraw(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         vertexCount,
+        u32                                         instanceCount,
+        u32                                         firstVertex,
+        u32                                         firstInstance) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdDrawIndexed(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         indexCount,
+        u32                                         instanceCount,
+        u32                                         firstIndex,
+        s32                                         vertexOffset,
+        u32                                         firstInstance) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdDrawIndirect(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        u32                                         drawCount,
+        u32                                         stride) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    bufferObject := GetBuffer(buffer)
+    assert(commandBufferObject.device == bufferObject.device)
+
+    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdDrawIndexedIndirect(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset,
+        u32                                         drawCount,
+        u32                                         stride) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    bufferObject := GetBuffer(buffer)
+    assert(commandBufferObject.device == bufferObject.device)
+
+    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdDispatch(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         x,
+        u32                                         y,
+        u32                                         z) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdDispatchIndirect(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    buffer,
+        VkDeviceSize                                offset) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    bufferObject := GetBuffer(buffer)
+    assert(commandBufferObject.device == bufferObject.device)
+
+    bindCommandBuffer(commandBuffer, buffer, bufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_COMPUTE_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdCopyBuffer(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    srcBuffer,
+        VkBuffer                                    dstBuffer,
+        u32                                         regionCount,
+        const VkBufferCopy*                         pRegions) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    srcBufferObject := GetBuffer(srcBuffer)
+    dstBufferObject := GetBuffer(dstBuffer)
+    assert(commandBufferObject.device == srcBufferObject.device)
+    assert(commandBufferObject.device == dstBufferObject.device)
+
+    regions := pRegions[0:regionCount]
+    for i in (0 .. regionCount) {
+        region := regions[i]
+    }
+
+    bindCommandBuffer(commandBuffer, srcBuffer, srcBufferObject.memory)
+    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdCopyImage(
+        VkCommandBuffer                             commandBuffer,
+        VkImage                                     srcImage,
+        VkImageLayout                               srcImageLayout,
+        VkImage                                     dstImage,
+        VkImageLayout                               dstImageLayout,
+        u32                                         regionCount,
+        const VkImageCopy*                          pRegions) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    srcImageObject := GetImage(srcImage)
+    dstImageObject := GetImage(dstImage)
+    assert(commandBufferObject.device == srcImageObject.device)
+    assert(commandBufferObject.device == dstImageObject.device)
+
+    regions := pRegions[0:regionCount]
+    for i in (0 .. regionCount) {
+        region := regions[i]
+    }
+
+    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
+    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdBlitImage(
+        VkCommandBuffer                             commandBuffer,
+        VkImage                                     srcImage,
+        VkImageLayout                               srcImageLayout,
+        VkImage                                     dstImage,
+        VkImageLayout                               dstImageLayout,
+        u32                                         regionCount,
+        const VkImageBlit*                          pRegions,
+        VkFilter                                    filter) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    srcImageObject := GetImage(srcImage)
+    dstImageObject := GetImage(dstImage)
+    assert(commandBufferObject.device == srcImageObject.device)
+    assert(commandBufferObject.device == dstImageObject.device)
+
+    regions := pRegions[0:regionCount]
+    for i in (0 .. regionCount) {
+        region := regions[i]
+    }
+
+    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
+    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdCopyBufferToImage(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    srcBuffer,
+        VkImage                                     dstImage,
+        VkImageLayout                               dstImageLayout,
+        u32                                         regionCount,
+        const VkBufferImageCopy*                    pRegions) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    srcBufferObject := GetBuffer(srcBuffer)
+    dstImageObject := GetImage(dstImage)
+    assert(commandBufferObject.device == srcBufferObject.device)
+    assert(commandBufferObject.device == dstImageObject.device)
+
+    regions := pRegions[0:regionCount]
+    for i in (0 .. regionCount) {
+        region := regions[i]
+    }
+
+    bindCommandBuffer(commandBuffer, srcBuffer, srcBufferObject.memory)
+    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdCopyImageToBuffer(
+        VkCommandBuffer                             commandBuffer,
+        VkImage                                     srcImage,
+        VkImageLayout                               srcImageLayout,
+        VkBuffer                                    dstBuffer,
+        u32                                         regionCount,
+        const VkBufferImageCopy*                    pRegions) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    srcImageObject := GetImage(srcImage)
+    dstBufferObject := GetBuffer(dstBuffer)
+    assert(commandBufferObject.device == srcImageObject.device)
+    assert(commandBufferObject.device == dstBufferObject.device)
+
+    regions := pRegions[0:regionCount]
+    for i in (0 .. regionCount) {
+        region := regions[i]
+    }
+
+    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
+    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdUpdateBuffer(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    dstBuffer,
+        VkDeviceSize                                dstOffset,
+        VkDeviceSize                                dataSize,
+        const u32*                                  pData) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    dstBufferObject := GetBuffer(dstBuffer)
+    assert(commandBufferObject.device == dstBufferObject.device)
+
+    data := pData[0:dataSize]
+
+    bindCommandBuffer(commandBuffer, dstBuffer, dstBufferObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdFillBuffer(
+        VkCommandBuffer                             commandBuffer,
+        VkBuffer                                    dstBuffer,
+        VkDeviceSize                                dstOffset,
+        VkDeviceSize                                size,
+        u32                                         data) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    dstBufferObject := GetBuffer(dstBuffer)
+    assert(commandBufferObject.device == dstBufferObject.device)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_TRANSFER_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdClearColorImage(
+        VkCommandBuffer                             commandBuffer,
+        VkImage                                     image,
+        VkImageLayout                               imageLayout,
+        const VkClearColorValue*                    pColor,
+        u32                                         rangeCount,
+        const VkImageSubresourceRange*              pRanges) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    imageObject := GetImage(image)
+    assert(commandBufferObject.device == imageObject.device)
+
+    ranges := pRanges[0:rangeCount]
+    for i in (0 .. rangeCount) {
+        range := ranges[i]
+    }
+
+    bindCommandBuffer(commandBuffer, image, imageObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdClearDepthStencilImage(
+        VkCommandBuffer                             commandBuffer,
+        VkImage                                     image,
+        VkImageLayout                               imageLayout,
+        const VkClearDepthStencilValue*             pDepthStencil,
+        u32                                         rangeCount,
+        const VkImageSubresourceRange*              pRanges) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    imageObject := GetImage(image)
+    assert(commandBufferObject.device == imageObject.device)
+
+    ranges := pRanges[0:rangeCount]
+    for i in (0 .. rangeCount) {
+        range := ranges[i]
+    }
+
+    bindCommandBuffer(commandBuffer, image, imageObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdClearAttachments(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         attachmentCount,
+        const VkClearAttachment*                    pAttachments,
+        u32                                         rectCount,
+        const VkClearRect*                          pRects) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    rects := pRects[0:rectCount]
+    for i in (0 .. rectCount) {
+        rect := rects[i]
+    }
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdResolveImage(
+        VkCommandBuffer                             commandBuffer,
+        VkImage                                     srcImage,
+        VkImageLayout                               srcImageLayout,
+        VkImage                                     dstImage,
+        VkImageLayout                               dstImageLayout,
+        u32                                         regionCount,
+        const VkImageResolve*                       pRegions) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    srcImageObject := GetImage(srcImage)
+    dstImageObject := GetImage(dstImage)
+    assert(commandBufferObject.device == srcImageObject.device)
+    assert(commandBufferObject.device == dstImageObject.device)
+
+    regions := pRegions[0:regionCount]
+    for i in (0 .. regionCount) {
+        region := regions[i]
+    }
+
+    bindCommandBuffer(commandBuffer, srcImage, srcImageObject.memory)
+    bindCommandBuffer(commandBuffer, dstImage, dstImageObject.memory)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+@threadSafety("app")
+cmd void vkCmdSetEvent(
+        VkCommandBuffer                             commandBuffer,
+        VkEvent                                     event,
+        VkPipelineStageFlags                        stageMask) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    eventObject := GetEvent(event)
+    assert(commandBufferObject.device == eventObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdResetEvent(
+        VkCommandBuffer                             commandBuffer,
+        VkEvent                                     event,
+        VkPipelineStageFlags                        stageMask) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    eventObject := GetEvent(event)
+    assert(commandBufferObject.device == eventObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdWaitEvents(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         eventCount,
+        const VkEvent*                              pEvents,
+        VkPipelineStageFlags                        srcStageMask,
+        VkPipelineStageFlags                        dstStageMask,
+        u32                                         memoryBarrierCount,
+        const VkMemoryBarrier*                      pMemoryBarriers,
+        u32                                         bufferMemoryBarrierCount,
+        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
+        u32                                         imageMemoryBarrierCount,
+        const VkImageMemoryBarrier*                 pImageMemoryBarriers) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    events := pEvents[0:eventCount]
+    for i in (0 .. eventCount) {
+        event := events[i]
+        eventObject := GetEvent(event)
+        assert(commandBufferObject.device == eventObject.device)
+    }
+
+    memoryBarriers := pMemoryBarriers[0:memoryBarrierCount]
+    for i in (0 .. memoryBarrierCount) {
+        memoryBarrier := memoryBarriers[i]
+    }
+    bufferMemoryBarriers := pBufferMemoryBarriers[0:bufferMemoryBarrierCount]
+    for i in (0 .. bufferMemoryBarrierCount) {
+        bufferMemoryBarrier := bufferMemoryBarriers[i]
+        bufferObject := GetBuffer(bufferMemoryBarrier.buffer)
+        assert(bufferObject.device == commandBufferObject.device)
+    }
+    imageMemoryBarriers := pImageMemoryBarriers[0:imageMemoryBarrierCount]
+    for i in (0 .. imageMemoryBarrierCount) {
+        imageMemoryBarrier := imageMemoryBarriers[i]
+        imageObject := GetImage(imageMemoryBarrier.image)
+        assert(imageObject.device == commandBufferObject.device)
+    }
+}
+
+@threadSafety("app")
+cmd void vkCmdPipelineBarrier(
+        VkCommandBuffer                             commandBuffer,
+        VkPipelineStageFlags                        srcStageMask,
+        VkPipelineStageFlags                        dstStageMask,
+        VkDependencyFlags                           dependencyFlags,
+        u32                                         memoryBarrierCount,
+        const VkMemoryBarrier*                      pMemoryBarriers,
+        u32                                         bufferMemoryBarrierCount,
+        const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
+        u32                                         imageMemoryBarrierCount,
+        const VkImageMemoryBarrier*                 pImageMemoryBarriers) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    memoryBarriers := pMemoryBarriers[0:memoryBarrierCount]
+    for i in (0 .. memoryBarrierCount) {
+        memoryBarrier := memoryBarriers[i]
+    }
+    bufferMemoryBarriers := pBufferMemoryBarriers[0:bufferMemoryBarrierCount]
+    for i in (0 .. bufferMemoryBarrierCount) {
+        bufferMemoryBarrier := bufferMemoryBarriers[i]
+        bufferObject := GetBuffer(bufferMemoryBarrier.buffer)
+        assert(bufferObject.device == commandBufferObject.device)
+    }
+    imageMemoryBarriers := pImageMemoryBarriers[0:imageMemoryBarrierCount]
+    for i in (0 .. imageMemoryBarrierCount) {
+        imageMemoryBarrier := imageMemoryBarriers[i]
+        imageObject := GetImage(imageMemoryBarrier.image)
+        assert(imageObject.device == commandBufferObject.device)
+    }
+}
+
+@threadSafety("app")
+cmd void vkCmdBeginQuery(
+        VkCommandBuffer                             commandBuffer,
+        VkQueryPool                                 queryPool,
+        u32                                         query,
+        VkQueryControlFlags                         flags) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    queryPoolObject := GetQueryPool(queryPool)
+    assert(commandBufferObject.device == queryPoolObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdEndQuery(
+        VkCommandBuffer                             commandBuffer,
+        VkQueryPool                                 queryPool,
+        u32                                         query) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    queryPoolObject := GetQueryPool(queryPool)
+    assert(commandBufferObject.device == queryPoolObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdResetQueryPool(
+        VkCommandBuffer                             commandBuffer,
+        VkQueryPool                                 queryPool,
+        u32                                         firstQuery,
+        u32                                         queryCount) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    queryPoolObject := GetQueryPool(queryPool)
+    assert(commandBufferObject.device == queryPoolObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdWriteTimestamp(
+        VkCommandBuffer                             commandBuffer,
+        VkPipelineStageFlagBits                     pipelineStage,
+        VkQueryPool                                 queryPool,
+        u32                                         query) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    queryPoolObject := GetQueryPool(queryPool)
+    assert(commandBufferObject.device == queryPoolObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdCopyQueryPoolResults(
+        VkCommandBuffer                             commandBuffer,
+        VkQueryPool                                 queryPool,
+        u32                                         firstQuery,
+        u32                                         queryCount,
+        VkBuffer                                    dstBuffer,
+        VkDeviceSize                                dstOffset,
+        VkDeviceSize                                stride,
+        VkQueryResultFlags                          flags) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    queryPoolObject := GetQueryPool(queryPool)
+    dstBufferObject := GetBuffer(dstBuffer)
+    assert(commandBufferObject.device == queryPoolObject.device)
+    assert(commandBufferObject.device == dstBufferObject.device)
+}
+
+cmd void vkCmdPushConstants(
+        VkCommandBuffer                             commandBuffer,
+        VkPipelineLayout                            layout,
+        VkShaderStageFlags                          stageFlags,
+        u32                                         offset,
+        u32                                         size,
+        const void*                                 pValues) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    layoutObject := GetPipelineLayout(layout)
+    assert(commandBufferObject.device == layoutObject.device)
+}
+
+@threadSafety("app")
+cmd void vkCmdBeginRenderPass(
+        VkCommandBuffer                             commandBuffer,
+        const VkRenderPassBeginInfo*                pRenderPassBegin,
+        VkSubpassContents                           contents) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+    renderPassObject := GetRenderPass(pRenderPassBegin.renderPass)
+    framebufferObject := GetFramebuffer(pRenderPassBegin.framebuffer)
+    assert(commandBufferObject.device == renderPassObject.device)
+    assert(commandBufferObject.device == framebufferObject.device)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+cmd void vkCmdNextSubpass(
+        VkCommandBuffer                             commandBuffer,
+        VkSubpassContents                           contents) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+}
+
+@threadSafety("app")
+cmd void vkCmdEndRenderPass(
+        VkCommandBuffer                             commandBuffer) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    commandBufferObject.queueFlags = AddQueueFlag(commandBufferObject.queueFlags, VK_QUEUE_GRAPHICS_BIT)
+}
+
+cmd void vkCmdExecuteCommands(
+        VkCommandBuffer                             commandBuffer,
+        u32                                         commandBufferCount,
+        const VkCommandBuffer*                      pCommandBuffers) {
+    commandBufferObject := GetCommandBuffer(commandBuffer)
+
+    commandBuffers := pCommandBuffers[0:commandBufferCount]
+    for i in (0 .. commandBufferCount) {
+        secondaryCommandBuffer := commandBuffers[i]
+        secondaryCommandBufferObject := GetCommandBuffer(secondaryCommandBuffer)
+        assert(commandBufferObject.device == secondaryCommandBufferObject.device)
+    }
+}
+
+@extension("VK_KHR_surface")
+cmd void vkDestroySurfaceKHR(
+        VkInstance                                  instance,
+        VkSurfaceKHR                                surface,
+        const VkAllocationCallbacks*                pAllocator) {
+    instanceObject := GetInstance(instance)
+    surfaceObject := GetSurface(surface)
+    assert(surfaceObject.instance == instance)
+
+    State.Surfaces[surface] = null
+}
+
+@extension("VK_KHR_surface")
+cmd VkResult vkGetPhysicalDeviceSurfaceSupportKHR(
+        VkPhysicalDevice                            physicalDevice,
+        u32                                         queueFamilyIndex,
+        VkSurfaceKHR                                surface,
+        VkBool32*                                   pSupported) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    return ?
+}
+
+@extension("VK_KHR_surface")
+cmd VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkSurfaceKHR                                surface,
+        VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    surfaceCapabilities := ?
+    pSurfaceCapabilities[0] = surfaceCapabilities
+
+    return ?
+}
+
+@extension("VK_KHR_surface")
+cmd VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkSurfaceKHR                                surface,
+        u32*                                        pSurfaceFormatCount,
+        VkSurfaceFormatKHR*                         pSurfaceFormats) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    count := as!u32(?)
+    pSurfaceFormatCount[0] = count
+    surfaceFormats := pSurfaceFormats[0:count]
+
+    for i in (0 .. count) {
+        surfaceFormat := ?
+        surfaceFormats[i] = surfaceFormat
+    }
+
+    return ?
+}
+
+@extension("VK_KHR_surface")
+cmd VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(
+        VkPhysicalDevice                            physicalDevice,
+        VkSurfaceKHR                                surface,
+        u32*                                        pPresentModeCount,
+        VkPresentModeKHR*                           pPresentModes) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+
+    count := as!u32(?)
+    pPresentModeCount[0] = count
+    presentModes := pPresentModes[0:count]
+
+    for i in (0 .. count) {
+        presentMode := ?
+        presentModes[i] = presentMode
+    }
+
+    return ?
+}
+
+@extension("VK_KHR_swapchain")
+cmd VkResult vkCreateSwapchainKHR(
+        VkDevice                                 device,
+        const VkSwapchainCreateInfoKHR*          pCreateInfo,
+        const VkAllocationCallbacks*             pAllocator,
+        VkSwapchainKHR*                          pSwapchain) {
+    assert(pCreateInfo.sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR)
+    deviceObject := GetDevice(device)
+
+    swapchain := ?
+    pSwapchain[0] = swapchain
+    State.Swapchains[swapchain] = new!SwapchainObject(device: device)
+
+    return ?
+}
+
+@extension("VK_KHR_swapchain")
+cmd void vkDestroySwapchainKHR(
+        VkDevice                                 device,
+        VkSwapchainKHR                           swapchain,
+        const VkAllocationCallbacks*             pAllocator) {
+    deviceObject := GetDevice(device)
+    swapchainObject := GetSwapchain(swapchain)
+    assert(swapchainObject.device == device)
+
+    State.Swapchains[swapchain] = null
+}
+
+@extension("VK_KHR_swapchain")
+cmd VkResult vkGetSwapchainImagesKHR(
+        VkDevice                                 device,
+        VkSwapchainKHR                           swapchain,
+        u32*                                     pSwapchainImageCount,
+        VkImage*                                 pSwapchainImages) {
+    deviceObject := GetDevice(device)
+
+    count := as!u32(?)
+    pSwapchainImageCount[0] = count
+    swapchainImages := pSwapchainImages[0:count]
+
+    for i in (0 .. count) {
+        swapchainImage := ?
+        swapchainImages[i] = swapchainImage
+        State.Images[swapchainImage] = new!ImageObject(device: device)
+    }
+
+    return ?
+}
+
+@extension("VK_KHR_swapchain")
+cmd VkResult vkAcquireNextImageKHR(
+        VkDevice                                 device,
+        VkSwapchainKHR                           swapchain,
+        u64                                      timeout,
+        VkSemaphore                              semaphore,
+        VkFence                                  fence,
+        u32*                                     pImageIndex) {
+    deviceObject := GetDevice(device)
+    swapchainObject := GetSwapchain(swapchain)
+
+    imageIndex := ?
+    pImageIndex[0] = imageIndex
+
+    return ?
+}
+
+@extension("VK_KHR_swapchain")
+cmd VkResult vkQueuePresentKHR(
+        VkQueue                                  queue,
+        const VkPresentInfoKHR*                  pPresentInfo) {
+    queueObject := GetQueue(queue)
+
+    presentInfo := ?
+    pPresentInfo[0] = presentInfo
+
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkGetPhysicalDeviceDisplayPropertiesKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32*                                    pPropertyCount,
+        VkDisplayPropertiesKHR*                 pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32*                                    pPropertyCount,
+        VkDisplayPlanePropertiesKHR*            pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkGetDisplayPlaneSupportedDisplaysKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32                                     planeIndex,
+        u32*                                    pDisplayCount,
+        VkDisplayKHR*                           pDisplays) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkGetDisplayModePropertiesKHR(
+        VkPhysicalDevice                        physicalDevice,
+        VkDisplayKHR                            display,
+        u32*                                    pPropertyCount,
+        VkDisplayModePropertiesKHR*             pProperties) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkCreateDisplayModeKHR(
+        VkPhysicalDevice                        physicalDevice,
+        VkDisplayKHR                            display,
+        const VkDisplayModeCreateInfoKHR*       pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkDisplayModeKHR*                       pMode) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkGetDisplayPlaneCapabilitiesKHR(
+        VkPhysicalDevice                        physicalDevice,
+        VkDisplayModeKHR                        mode,
+        u32                                     planeIndex,
+        VkDisplayPlaneCapabilitiesKHR*          pCapabilities) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_display")
+cmd VkResult vkCreateDisplayPlaneSurfaceKHR(
+        VkInstance                              instance,
+        const VkDisplaySurfaceCreateInfoKHR*    pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    return ?
+}
+
+@extension("VK_KHR_display_swapchain")
+cmd VkResult vkCreateSharedSwapchainsKHR(
+        VkDevice                                device,
+        u32                                     swapchainCount,
+        const VkSwapchainCreateInfoKHR*         pCreateInfos,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSwapchainKHR*                         pSwapchains) {
+    return ?
+}
+
+@extension("VK_KHR_xlib_surface")
+cmd VkResult vkCreateXlibSurfaceKHR(
+        VkInstance                              instance,
+        const VkXlibSurfaceCreateInfoKHR*       pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    instanceObject := GetInstance(instance)
+    return ?
+}
+
+@extension("VK_KHR_xlib_surface")
+cmd VkBool32 vkGetPhysicalDeviceXlibPresentationSupportKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32                                     queueFamilyIndex,
+        platform.Display*                       dpy,
+        platform.VisualID                       visualID) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_xcb_surface")
+cmd VkResult vkCreateXcbSurfaceKHR(
+        VkInstance                              instance,
+        const VkXcbSurfaceCreateInfoKHR*        pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    instanceObject := GetInstance(instance)
+    return ?
+}
+
+@extension("VK_KHR_xcb_surface")
+cmd VkBool32 vkGetPhysicalDeviceXcbPresentationSupportKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32                                     queueFamilyIndex,
+        platform.xcb_connection_t*              connection,
+        platform.xcb_visualid_t                 visual_id) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_wayland_surface")
+cmd VkResult vkCreateWaylandSurfaceKHR(
+        VkInstance                              instance,
+        const VkWaylandSurfaceCreateInfoKHR*    pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    instanceObject := GetInstance(instance)
+    return ?
+}
+
+@extension("VK_KHR_wayland_surface")
+cmd VkBool32 vkGetPhysicalDeviceWaylandPresentationSupportKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32                                     queueFamilyIndex,
+        platform.wl_display*                    display) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_mir_surface")
+cmd VkResult vkCreateMirSurfaceKHR(
+        VkInstance                              instance,
+        const VkMirSurfaceCreateInfoKHR*        pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    instanceObject := GetInstance(instance)
+    return ?
+}
+
+@extension("VK_KHR_mir_surface")
+cmd VkBool32 vkGetPhysicalDeviceMirPresentationSupportKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32                                     queueFamilyIndex,
+        platform.MirConnection*                 connection) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_KHR_android_surface")
+cmd VkResult vkCreateAndroidSurfaceKHR(
+        VkInstance                              instance,
+        const VkAndroidSurfaceCreateInfoKHR*    pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    instanceObject := GetInstance(instance)
+    return ?
+}
+
+@extension("VK_KHR_win32_surface")
+cmd VkResult vkCreateWin32SurfaceKHR(
+        VkInstance                              instance,
+        const VkWin32SurfaceCreateInfoKHR*      pCreateInfo,
+        const VkAllocationCallbacks*            pAllocator,
+        VkSurfaceKHR*                           pSurface) {
+    instanceObject := GetInstance(instance)
+    return ?
+}
+
+@extension("VK_KHR_win32_surface")
+cmd VkResult vkGetPhysicalDeviceWin32PresentationSupportKHR(
+        VkPhysicalDevice                        physicalDevice,
+        u32                                     queueFamilyIndex) {
+    physicalDeviceObject := GetPhysicalDevice(physicalDevice)
+    return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkGetSwapchainGrallocUsageANDROID(
+        VkDevice                                device,
+        VkFormat                                format,
+        VkImageUsageFlags                       imageUsage,
+        int*                                    grallocUsage) {
+    return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkAcquireImageANDROID(
+        VkDevice                                device,
+        VkImage                                 image,
+        int                                     nativeFenceFd,
+        VkSemaphore                             semaphore,
+        VkFence                                 fence) {
+    return ?
+}
+
+@extension("VK_ANDROID_native_buffer")
+cmd VkResult vkQueueSignalReleaseImageANDROID(
+        VkQueue                                 queue,
+        u32                                     waitSemaphoreCount,
+        const VkSemaphore*                      pWaitSemaphores,
+        VkImage                                 image,
+        int*                                    pNativeFenceFd) {
+    return ?
+}
+
+@extension("VK_EXT_debug_report")
+@external type void* PFN_vkDebugReportCallbackEXT
+@extension("VK_EXT_debug_report")
+@pfn cmd VkBool32 vkDebugReportCallbackEXT(
+        VkDebugReportFlagsEXT                   flags,
+        VkDebugReportObjectTypeEXT              objectType,
+        u64                                     object,
+        platform.size_t                         location,
+        s32                                     messageCode,
+        const char*                             pLayerPrefix,
+        const char*                             pMessage,
+        void*                                   pUserData) {
+    return ?
+}
+
+@extension("VK_EXT_debug_report")
+cmd VkResult vkCreateDebugReportCallbackEXT(
+        VkInstance                                  instance,
+        const VkDebugReportCallbackCreateInfoEXT*   pCreateInfo,
+        const VkAllocationCallbacks*                pAllocator,
+        VkDebugReportCallbackEXT*                   pCallback) {
+    return ?
+}
+
+@extension("VK_EXT_debug_report")
+cmd void vkDestroyDebugReportCallbackEXT(
+        VkInstance                                  instance,
+        VkDebugReportCallbackEXT                    callback,
+        const VkAllocationCallbacks*                pAllocator) {
+}
+
+@extension("VK_EXT_debug_report")
+cmd void vkDebugReportMessageEXT(
+        VkInstance                                  instance,
+        VkDebugReportFlagsEXT                       flags,
+        VkDebugReportObjectTypeEXT                  objectType,
+        u64                                         object,
+        platform.size_t                             location,
+        s32                                         messageCode,
+        const char*                                 pLayerPrefix,
+        const char*                                 pMessage) {
+}
+
+
+////////////////
+// Validation //
+////////////////
+
+extern void validate(string layerName, bool condition, string message)
+
+
+/////////////////////////////
+// Internal State Tracking //
+/////////////////////////////
+
+StateObject State
+
+@internal class StateObject {
+    // Dispatchable objects.
+    map!(VkInstance,       ref!InstanceObject)       Instances
+    map!(VkPhysicalDevice, ref!PhysicalDeviceObject) PhysicalDevices
+    map!(VkDevice,         ref!DeviceObject)         Devices
+    map!(VkQueue,          ref!QueueObject)          Queues
+    map!(VkCommandBuffer,  ref!CommandBufferObject)  CommandBuffers
+
+    // Non-dispatchable objects.
+    map!(VkDeviceMemory,             ref!DeviceMemoryObject)             DeviceMemories
+    map!(VkBuffer,                   ref!BufferObject)                   Buffers
+    map!(VkBufferView,               ref!BufferViewObject)               BufferViews
+    map!(VkImage,                    ref!ImageObject)                    Images
+    map!(VkImageView,                ref!ImageViewObject)                ImageViews
+    map!(VkShaderModule,             ref!ShaderModuleObject)             ShaderModules
+    map!(VkPipeline,                 ref!PipelineObject)                 Pipelines
+    map!(VkPipelineLayout,           ref!PipelineLayoutObject)           PipelineLayouts
+    map!(VkSampler,                  ref!SamplerObject)                  Samplers
+    map!(VkDescriptorSet,            ref!DescriptorSetObject)            DescriptorSets
+    map!(VkDescriptorSetLayout,      ref!DescriptorSetLayoutObject)      DescriptorSetLayouts
+    map!(VkDescriptorPool,           ref!DescriptorPoolObject)           DescriptorPools
+    map!(VkFence,                    ref!FenceObject)                    Fences
+    map!(VkSemaphore,                ref!SemaphoreObject)                Semaphores
+    map!(VkEvent,                    ref!EventObject)                    Events
+    map!(VkQueryPool,                ref!QueryPoolObject)                QueryPools
+    map!(VkFramebuffer,              ref!FramebufferObject)              Framebuffers
+    map!(VkRenderPass,               ref!RenderPassObject)               RenderPasses
+    map!(VkPipelineCache,            ref!PipelineCacheObject)            PipelineCaches
+    map!(VkCommandPool,              ref!CommandPoolObject)              CommandPools
+    map!(VkSurfaceKHR,               ref!SurfaceObject)                  Surfaces
+    map!(VkSwapchainKHR,             ref!SwapchainObject)                Swapchains
+}
+
+@internal class InstanceObject {
+}
+
+@internal class PhysicalDeviceObject {
+    VkInstance instance
+}
+
+@internal class DeviceObject {
+    VkPhysicalDevice physicalDevice
+}
+
+@internal class QueueObject {
+    VkDevice      device
+    VkQueueFlags  flags
+}
+
+@internal class CommandBufferObject {
+    VkDevice                  device
+    map!(u64, VkDeviceMemory) boundObjects
+    VkQueueFlags              queueFlags
+}
+
+@internal class DeviceMemoryObject {
+    VkDevice                                device
+    VkDeviceSize                            allocationSize
+    map!(u64, VkDeviceSize)                 boundObjects
+    map!(VkCommandBuffer, VkCommandBuffer)  boundCommandBuffers
+}
+
+@internal class BufferObject {
+    VkDevice              device
+    VkDeviceMemory        memory
+    VkDeviceSize          memoryOffset
+}
+
+@internal class BufferViewObject {
+    VkDevice      device
+    VkBuffer      buffer
+}
+
+@internal class ImageObject {
+    VkDevice              device
+    VkDeviceMemory        memory
+    VkDeviceSize          memoryOffset
+}
+
+@internal class ImageViewObject {
+    VkDevice      device
+    VkImage       image
+}
+
+@internal class ShaderObject {
+    VkDevice      device
+}
+
+@internal class ShaderModuleObject {
+    VkDevice      device
+}
+
+@internal class PipelineObject {
+    VkDevice      device
+}
+
+@internal class PipelineLayoutObject {
+    VkDevice      device
+}
+
+@internal class SamplerObject {
+    VkDevice      device
+}
+
+@internal class DescriptorSetObject {
+    VkDevice      device
+}
+
+@internal class DescriptorSetLayoutObject {
+    VkDevice      device
+}
+
+@internal class DescriptorPoolObject {
+    VkDevice      device
+}
+
+@internal class FenceObject {
+    VkDevice      device
+    bool          signaled
+}
+
+@internal class SemaphoreObject {
+    VkDevice      device
+}
+
+@internal class EventObject {
+    VkDevice      device
+}
+
+@internal class QueryPoolObject {
+    VkDevice      device
+}
+
+@internal class FramebufferObject {
+    VkDevice      device
+}
+
+@internal class RenderPassObject {
+    VkDevice      device
+}
+
+@internal class PipelineCacheObject {
+    VkDevice      device
+}
+
+@internal class CommandPoolObject {
+    VkDevice      device
+}
+
+@internal class SurfaceObject {
+    VkInstance    instance
+}
+
+@internal class SwapchainObject {
+    VkDevice      device
+}
+
+macro ref!InstanceObject GetInstance(VkInstance instance) {
+    assert(instance in State.Instances)
+    return State.Instances[instance]
+}
+
+macro ref!PhysicalDeviceObject GetPhysicalDevice(VkPhysicalDevice physicalDevice) {
+    assert(physicalDevice in State.PhysicalDevices)
+    return State.PhysicalDevices[physicalDevice]
+}
+
+macro ref!DeviceObject GetDevice(VkDevice device) {
+    assert(device in State.Devices)
+    return State.Devices[device]
+}
+
+macro ref!QueueObject GetQueue(VkQueue queue) {
+    assert(queue in State.Queues)
+    return State.Queues[queue]
+}
+
+macro ref!CommandBufferObject GetCommandBuffer(VkCommandBuffer commandBuffer) {
+    assert(commandBuffer in State.CommandBuffers)
+    return State.CommandBuffers[commandBuffer]
+}
+
+macro ref!DeviceMemoryObject GetDeviceMemory(VkDeviceMemory memory) {
+    assert(memory in State.DeviceMemories)
+    return State.DeviceMemories[memory]
+}
+
+macro ref!BufferObject GetBuffer(VkBuffer buffer) {
+    assert(buffer in State.Buffers)
+    return State.Buffers[buffer]
+}
+
+macro ref!BufferViewObject GetBufferView(VkBufferView bufferView) {
+    assert(bufferView in State.BufferViews)
+    return State.BufferViews[bufferView]
+}
+
+macro ref!ImageObject GetImage(VkImage image) {
+    assert(image in State.Images)
+    return State.Images[image]
+}
+
+macro ref!ImageViewObject GetImageView(VkImageView imageView) {
+    assert(imageView in State.ImageViews)
+    return State.ImageViews[imageView]
+}
+
+macro ref!ShaderModuleObject GetShaderModule(VkShaderModule shaderModule) {
+    assert(shaderModule in State.ShaderModules)
+    return State.ShaderModules[shaderModule]
+}
+
+macro ref!PipelineObject GetPipeline(VkPipeline pipeline) {
+    assert(pipeline in State.Pipelines)
+    return State.Pipelines[pipeline]
+}
+
+macro ref!PipelineLayoutObject GetPipelineLayout(VkPipelineLayout pipelineLayout) {
+    assert(pipelineLayout in State.PipelineLayouts)
+    return State.PipelineLayouts[pipelineLayout]
+}
+
+macro ref!SamplerObject GetSampler(VkSampler sampler) {
+    assert(sampler in State.Samplers)
+    return State.Samplers[sampler]
+}
+
+macro ref!DescriptorSetObject GetDescriptorSet(VkDescriptorSet descriptorSet) {
+    assert(descriptorSet in State.DescriptorSets)
+    return State.DescriptorSets[descriptorSet]
+}
+
+macro ref!DescriptorSetLayoutObject GetDescriptorSetLayout(VkDescriptorSetLayout descriptorSetLayout) {
+    assert(descriptorSetLayout in State.DescriptorSetLayouts)
+    return State.DescriptorSetLayouts[descriptorSetLayout]
+}
+
+macro ref!DescriptorPoolObject GetDescriptorPool(VkDescriptorPool descriptorPool) {
+    assert(descriptorPool in State.DescriptorPools)
+    return State.DescriptorPools[descriptorPool]
+}
+
+macro ref!FenceObject GetFence(VkFence fence) {
+    assert(fence in State.Fences)
+    return State.Fences[fence]
+}
+
+macro ref!SemaphoreObject GetSemaphore(VkSemaphore semaphore) {
+    assert(semaphore in State.Semaphores)
+    return State.Semaphores[semaphore]
+}
+
+macro ref!EventObject GetEvent(VkEvent event) {
+    assert(event in State.Events)
+    return State.Events[event]
+}
+
+macro ref!QueryPoolObject GetQueryPool(VkQueryPool queryPool) {
+    assert(queryPool in State.QueryPools)
+    return State.QueryPools[queryPool]
+}
+
+macro ref!FramebufferObject GetFramebuffer(VkFramebuffer framebuffer) {
+    assert(framebuffer in State.Framebuffers)
+    return State.Framebuffers[framebuffer]
+}
+
+macro ref!RenderPassObject GetRenderPass(VkRenderPass renderPass) {
+    assert(renderPass in State.RenderPasses)
+    return State.RenderPasses[renderPass]
+}
+
+macro ref!PipelineCacheObject GetPipelineCache(VkPipelineCache pipelineCache) {
+    assert(pipelineCache in State.PipelineCaches)
+    return State.PipelineCaches[pipelineCache]
+}
+
+macro ref!CommandPoolObject GetCommandPool(VkCommandPool commandPool) {
+    assert(commandPool in State.CommandPools)
+    return State.CommandPools[commandPool]
+}
+
+macro ref!SurfaceObject GetSurface(VkSurfaceKHR surface) {
+    assert(surface in State.Surfaces)
+    return State.Surfaces[surface]
+}
+
+macro ref!SwapchainObject GetSwapchain(VkSwapchainKHR swapchain) {
+    assert(swapchain in State.Swapchains)
+    return State.Swapchains[swapchain]
+}
+
+macro VkQueueFlags AddQueueFlag(VkQueueFlags flags, VkQueueFlagBits bit) {
+    return as!VkQueueFlags(as!u32(flags) | as!u32(bit))
+}
diff --git a/vulkan/doc/DevelopersGuide.pdf b/vulkan/doc/DevelopersGuide.pdf
new file mode 100644
index 0000000..cf009c5
--- /dev/null
+++ b/vulkan/doc/DevelopersGuide.pdf
Binary files differ
diff --git a/vulkan/doc/implementors_guide/implementors_guide-docinfo.adoc b/vulkan/doc/implementors_guide/implementors_guide-docinfo.adoc
new file mode 100644
index 0000000..69b8c61
--- /dev/null
+++ b/vulkan/doc/implementors_guide/implementors_guide-docinfo.adoc
@@ -0,0 +1,23 @@
+<style type="text/css">
+
+code,div.listingblock {
+	max-width: 68em;
+}
+
+p {
+    max-width: 50em;
+}
+
+table {
+    max-width: 50em;
+}
+
+table.tableblock {
+  border-width: 1px;
+}
+
+h2 {
+    max-width: 35em;
+}
+
+</style>
diff --git a/vulkan/doc/implementors_guide/implementors_guide.adoc b/vulkan/doc/implementors_guide/implementors_guide.adoc
new file mode 100644
index 0000000..ae46f43
--- /dev/null
+++ b/vulkan/doc/implementors_guide/implementors_guide.adoc
@@ -0,0 +1,165 @@
+// asciidoc -b html5 -d book -f implementors_guide.conf implementors_guide.adoc
+= Vulkan on Android Implementor's Guide =
+:toc: right
+:numbered:
+:revnumber: 5
+
+This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.
+
+This is still a fairly rough draft; details will be filled in over time.
+
+== Architecture ==
+
+The primary interface between Vulkan applications and a device's Vulkan driver is the loader, which is part of AOSP and installed at +/system/lib[64]/libvulkan.so+. The loader provides the core Vulkan API entry points, as well as entry points of a few extensions that are required on Android and always present. In particular, the window system integration (WSI) extensions are exported by the loader and primarily implemented in it rather than the driver. The loader also supports enumerating and loading layers which can expose additional extensions and/or intercept core API calls on their way to the driver.
+
+The NDK will include a stub +libvulkan.so+ exporting the same symbols as the loader. Calling the Vulkan functions exported from +libvulkan.so+ will enter trampoline functions in the loader which will dispatch to the appropriate layer or driver based on their first argument. The +vkGet*ProcAddr+ calls will return the function pointers that the trampolines would dispatch to, so calling through these function pointers rather than the exported symbols will be slightly more efficient since it skips the trampoline and dispatch.
+
+=== Driver Enumeration and Loading ===
+
+Android expects the GPUs available to the system to be known when the system image is built, so its driver enumeration process isn't as elaborate as other platforms. The loader will use the existing HAL mechanism (see https://android.googlesource.com/platform/hardware/libhardware/+/lollipop-mr1-release/include/hardware/hardware.h[hardware.h]) for discovering and loading the driver. As of this writing, the preferred paths for 32-bit and 64-bit Vulkan drivers are:
+
+    /vendor/lib/hw/vulkan.<ro.product.platform>.so
+    /vendor/lib64/hw/vulkan.<ro.product.platform>.so
+
+where +<ro.product.platform>+ is replaced by the value of the system property of that name. See https://android.googlesource.com/platform/hardware/libhardware/+/lollipop-mr1-release/hardware.c[libhardware/hardware.c] for details and supported alternative locations.
+
+The Vulkan +hw_module_t+ derivative is currently trivial. If support for multiple drivers is ever added, the HAL module will export a list of strings that can be passed to the module +open+ call. For the time being, only one driver is supported, and the constant string +HWVULKAN_DEVICE_0+ is passed to +open+.
+
+The Vulkan +hw_device_t+ derivative corresponds to a single driver, though that driver can support multiple physical devices. The +hw_device_t+ structure will be extended to export +vkGetGlobalExtensionProperties+, +vkCreateInstance+, and +vkGetInstanceProcAddr+ functions. The loader will find all other +VkInstance+, +VkPhysicalDevice+, and +vkGetDeviceProcAddr+ functions by calling +vkGetInstanceProcAddr+.
+
+=== Layer Discovery and Loading ===
+
+Android's security model and policies differ significantly from other platforms. In particular, Android does not allow loading external code into a non-debuggable process on production (non-rooted) devices, nor does it allow external code to inspect or control the process's memory/state/etc. This includes a prohibition on saving core dumps, API traces, etc. to disk for later inspection. So only layers delivered as part of the application will be enabled on production devices, and drivers must also not provide functionality that violates these policies.
+
+There are three major use cases for layers:
+
+1. Development-time layers: validation layers, shims for tracing/profiling/debugging tools, etc. These shouldn't be installed on the system image of production devices: they would be a waste of space for most users, and they should be updateable without requiring a system update. A developer wishing to use one of these during development has the ability to modify their application package (e.g. adding a file to their native libraries directory). IHV and OEM engineers who are trying to diagnose failures in shipping, unmodifiable apps are assumed to have access to non-production (rooted) builds of the system image.
+
+2. Utility layers, such as a layer that implements a heap for device memory. These layers will almost always expose extensions. Developers choose which layers, and which versions of those layers, to use in their application; different applications that use the same layer may still use different versions. Developers will choose which of these layers to ship in their application package.
+
+3. Injected layers, like framerate, social network, or game launcher overlays, which are provided by the user or some other application without the application's knowledge or consent. These violate Android's security policies and will not be supported.
+
+In the normal state the loader will only search in the application's native library directory for layers; details are TBD but it will probably just try to load any library with a name matching a particular pattern(e.g. +libvklayer_foo.so+). It will probably not need a separate manifest file; the developer deliberately included these layers, so the reasons to avoid loading libraries before enabling them don't apply.
+
+On debuggable devices (+ro.debuggable+ property exists and is non-zero, generally rooted or engineering builds) or debuggable processes (+prctl(PR_GET_DUMPABLE)==1+, based on the application's manifest), the loader may also search an adb-writeable location on /data for layers. It's not clear whether this is useful; in all the cases it could be used, the layer could be just as easily be put in the application's native library directory.
+
+Finally, the loader may include a built-in validation layer that it will enable based on settings in the Developer Options menu, which would send validation errors or warnings to the system log. Drivers may be able to emit additional hardware-specific errors/warnings through this mechanism. This layer would not be enumerated through the API. This is intended to allow cooperative end-users to collect extra information about failures from unmodified applications on unmodified devices to aid triage/diagnosis of difficult-to-reproduce problems. The functionality would be intentionally limited to minimize security and privacy risk.
+
+Our goal is to allow layers to be ported with only build-environment changes between Android and other platforms. This means the interface between layers and the loader must match the interface used by the LunarG loader. Currently, the LunarG interface has a few deficiencies and is largely unspecified. We intend to work with LunarG to correct as many deficiencies as we can and to specify the interface in detail so that layers can be implemented without referring to the loader source code.
+
+== Window System Integration ==
+
+The +vk_wsi_swapchin+ and +vk_wsi_device_swapchain+ extensions will primarily be implemented by the platform and live in +libvulkan.so+. The +VkSwapchain+ object and all interaction with +ANativeWindow+ will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver's +vkGetDeviceProcAddr+ functions, after passing through any enabled layers.
+
+Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling
+[source,c]
+----
+VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
+    int*                grallocUsage
+);
+----
+The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.
+
++VkNativeBufferANDROID+ is a +vkCreateImage+ extension structure for creating an image backed by a gralloc buffer. This structure is provided to +vkCreateImage+ in the +VkImageCreateInfo+ structure chain. Calls to +vkCreateImage+ with this structure will happen during the first call to +vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)+. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a +VkImage+ for each one.
+
+[source,c]
+----
+typedef struct {
+    VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
+    const void*                 pNext;
+
+    // Buffer handle and stride returned from gralloc alloc()
+    buffer_handle_t             handle;
+    int                         stride;
+
+    // Gralloc format and usage requested when the buffer was allocated.
+    int                         format;
+    int                         usage;
+} VkNativeBufferANDROID;
+----
+
+TBD: During swapchain re-creation (using +oldSwapChain+), we may have to defer allocation of new gralloc buffers until old buffers have been released. If so, the +vkCreateImage+ calls will be deferred until the first +vkAcquireNextImageWSI+ that would return the new image.
+
+When creating a gralloc-backed image, the +VkImageCreateInfo+ will have:
+----
+  .imageType           = VK_IMAGE_TYPE_2D
+  .format              = a VkFormat matching the format requested for the gralloc buffer
+  .extent              = the 2D dimensions requested for the gralloc buffer
+  .mipLevels           = 1
+  .arraySize           = 1
+  .samples             = 1
+  .tiling              = VK_IMAGE_TILING_OPTIMAL
+  .usage               = VkSwapChainCreateInfoWSI::imageUsageFlags
+  .flags               = 0
+  .sharingMode         = VkSwapChainCreateInfoWSI::sharingMode
+  .queueFamilyCount    = VkSwapChainCreateInfoWSI::queueFamilyCount
+  .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices
+----
+
++vkAcquireImageANDROID+ acquires ownership of a swapchain image and imports an
+externally-signalled native fence into both an existing VkSemaphore object
+and an existing VkFence object:
+
+[source,c]
+----
+VkResult VKAPI vkAcquireImageANDROID(
+    VkDevice            device,
+    VkImage             image,
+    int                 nativeFenceFd,
+    VkSemaphore         semaphore,
+    VkFence             fence
+);
+----
+
+This function is called during +vkAcquireNextImageWSI+ to import a native
+fence into the +VkSemaphore+ and +VkFence+ objects provided by the
+application. Both semaphore and fence objects are optional in this call. The
+driver may also use this opportunity to recognize and handle any external
+changes to the gralloc buffer state; many drivers won't need to do anything
+here. This call puts the +VkSemaphore+ and +VkFence+ into the same "pending"
+state as +vkQueueSignalSemaphore+ and +vkQueueSubmit+ respectively, so queues
+can wait on the semaphore and the application can wait on the fence. Both
+objects become signalled when the underlying native fence signals; if the
+native fence has already signalled, then the semaphore will be in the signalled
+state when this function returns. The driver takes ownership of the fence fd
+and is responsible for closing it when no longer needed. It must do so even if
+neither a semaphore or fence object is provided, or even if
++vkAcquireImageANDROID+ fails and returns an error. If +fenceFd+ is -1, it
+is as if the native fence was already signalled.
+
++vkQueueSignalReleaseImageANDROID+ prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.
+
+[source,c]
+----
+VkResult VKAPI vkQueueSignalReleaseImageANDROID(
+    VkQueue             queue,
+    uint32_t            waitSemaphoreCount,
+    const VkSemaphore*  pWaitSemaphores,
+    VkImage             image,
+    int*                pNativeFenceFd
+);
+----
+
+This will be called during +vkQueuePresentWSI+ on the provided queue. Effects are similar to +vkQueueSignalSemaphore+, except with a native fence instead of a semaphore. The native fence must: not signal until the +waitSemaphoreCount+ semaphores in +pWaitSemaphores+ have signaled. Unlike +vkQueueSignalSemaphore+, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set +*pNativeFenceFd+ to -1. The file descriptor returned in +*pNativeFenceFd+ is owned and will be closed by the caller. Many drivers will be able to ignore the +image+ parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to +VK_IMAGE_LAYOUT_PRESENT_SRC_KHR+.
+
+== History ==
+
+. *2015-07-08* Initial version
+. *2015-08-16*
+   * Renamed to Implementor's Guide
+   * Wording and formatting changes
+   * Updated based on resolution of Khronos bug 14265
+   * Deferred support for multiple drivers
+. *2015-11-04*
+   * Added vkGetSwapchainGrallocUsageANDROID
+   * Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
+     with vkAcquireImageANDROID and vkQueueSignalReleaseImageANDROID, to allow
+     drivers to known the ownership state of swapchain images.
+. *2015-12-03*
+   * Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
+     parameter added to vkAcquireNextImageKHR.
+. *2016-01-08*
+   * Added waitSemaphoreCount and pWaitSemaphores parameters to vkQueueSignalReleaseImageANDROID.
\ No newline at end of file
diff --git a/vulkan/doc/implementors_guide/implementors_guide.conf b/vulkan/doc/implementors_guide/implementors_guide.conf
new file mode 100644
index 0000000..572a4d9
--- /dev/null
+++ b/vulkan/doc/implementors_guide/implementors_guide.conf
@@ -0,0 +1,5 @@
+[attributes]
+newline=\n
+
+[replacements]
+\+\/-=&plusmn;
diff --git a/vulkan/doc/implementors_guide/implementors_guide.html b/vulkan/doc/implementors_guide/implementors_guide.html
new file mode 100644
index 0000000..58ce0dc
--- /dev/null
+++ b/vulkan/doc/implementors_guide/implementors_guide.html
@@ -0,0 +1,984 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<meta name="generator" content="AsciiDoc 8.6.9">
+<title>Vulkan on Android Implementor&#8217;s Guide</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+  font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+  font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+  margin: 1em 5% 1em 5%;
+}
+
+a {
+  color: blue;
+  text-decoration: underline;
+}
+a:visited {
+  color: fuchsia;
+}
+
+em {
+  font-style: italic;
+  color: navy;
+}
+
+strong {
+  font-weight: bold;
+  color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  color: #527bbd;
+  margin-top: 1.2em;
+  margin-bottom: 0.5em;
+  line-height: 1.3;
+}
+
+h1, h2, h3 {
+  border-bottom: 2px solid silver;
+}
+h2 {
+  padding-top: 0.5em;
+}
+h3 {
+  float: left;
+}
+h3 + * {
+  clear: left;
+}
+h5 {
+  font-size: 1.0em;
+}
+
+div.sectionbody {
+  margin-left: 0;
+}
+
+hr {
+  border: 1px solid silver;
+}
+
+p {
+  margin-top: 0.5em;
+  margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+  margin-top: 0;
+}
+ul > li     { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+  font-family: "Courier New", Courier, monospace;
+  font-size: inherit;
+  color: navy;
+  padding: 0;
+  margin: 0;
+}
+pre {
+  white-space: pre-wrap;
+}
+
+#author {
+  color: #527bbd;
+  font-weight: bold;
+  font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+  font-size: small;
+  border-top: 2px solid silver;
+  padding-top: 0.5em;
+  margin-top: 4.0em;
+}
+#footer-text {
+  float: left;
+  padding-bottom: 0.5em;
+}
+#footer-badges {
+  float: right;
+  padding-bottom: 0.5em;
+}
+
+#preamble {
+  margin-top: 1.5em;
+  margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.admonitionblock {
+  margin-top: 2.0em;
+  margin-bottom: 2.0em;
+  margin-right: 10%;
+  color: #606060;
+}
+
+div.content { /* Block element content. */
+  padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+  color: #527bbd;
+  font-weight: bold;
+  text-align: left;
+  margin-top: 1.0em;
+  margin-bottom: 0.5em;
+}
+div.title + * {
+  margin-top: 0;
+}
+
+td div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content div.title:first-child {
+  margin-top: 0.0em;
+}
+div.content + div.title {
+  margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+  background: #ffffee;
+  border: 1px solid #dddddd;
+  border-left: 4px solid #f0f0f0;
+  padding: 0.5em;
+}
+
+div.listingblock > div.content {
+  border: 1px solid #dddddd;
+  border-left: 5px solid #f0f0f0;
+  background: #f8f8f8;
+  padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+  padding-left: 1.0em;
+  margin-left: 1.0em;
+  margin-right: 10%;
+  border-left: 5px solid #f0f0f0;
+  color: #888;
+}
+
+div.quoteblock > div.attribution {
+  padding-top: 0.5em;
+  text-align: right;
+}
+
+div.verseblock > pre.content {
+  font-family: inherit;
+  font-size: inherit;
+}
+div.verseblock > div.attribution {
+  padding-top: 0.75em;
+  text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+  text-align: left;
+}
+
+div.admonitionblock .icon {
+  vertical-align: top;
+  font-size: 1.1em;
+  font-weight: bold;
+  text-decoration: underline;
+  color: #527bbd;
+  padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+  padding-left: 0.5em;
+  border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+  border-left: 3px solid #dddddd;
+  padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+dt {
+  margin-top: 0.5em;
+  margin-bottom: 0;
+  font-style: normal;
+  color: navy;
+}
+dd > *:first-child {
+  margin-top: 0.1em;
+}
+
+ul, ol {
+    list-style-position: outside;
+}
+ol.arabic {
+  list-style-type: decimal;
+}
+ol.loweralpha {
+  list-style-type: lower-alpha;
+}
+ol.upperalpha {
+  list-style-type: upper-alpha;
+}
+ol.lowerroman {
+  list-style-type: lower-roman;
+}
+ol.upperroman {
+  list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+  margin-top: 0.1em;
+  margin-bottom: 0.1em;
+}
+
+tfoot {
+  font-weight: bold;
+}
+td > div.verse {
+  white-space: pre;
+}
+
+div.hdlist {
+  margin-top: 0.8em;
+  margin-bottom: 0.8em;
+}
+div.hdlist tr {
+  padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+  font-weight: bold;
+}
+td.hdlist1 {
+  vertical-align: top;
+  font-style: normal;
+  padding-right: 0.8em;
+  color: navy;
+}
+td.hdlist2 {
+  vertical-align: top;
+}
+div.hdlist.compact tr {
+  margin: 0;
+  padding-bottom: 0;
+}
+
+.comment {
+  background: yellow;
+}
+
+.footnote, .footnoteref {
+  font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+  vertical-align: super;
+}
+
+#footnotes {
+  margin: 20px 0 20px 0;
+  padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+  margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+  border: none;
+  border-top: 1px solid silver;
+  height: 1px;
+  text-align: left;
+  margin-left: 0;
+  width: 20%;
+  min-width: 100px;
+}
+
+div.colist td {
+  padding-right: 0.5em;
+  padding-bottom: 0.3em;
+  vertical-align: top;
+}
+div.colist td img {
+  margin-top: 0.3em;
+}
+
+@media print {
+  #footer-badges { display: none; }
+}
+
+#toc {
+  margin-bottom: 2.5em;
+}
+
+#toctitle {
+  color: #527bbd;
+  font-size: 1.1em;
+  font-weight: bold;
+  margin-top: 1.0em;
+  margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+  margin-top: 0;
+  margin-bottom: 0;
+}
+div.toclevel2 {
+  margin-left: 2em;
+  font-size: 0.9em;
+}
+div.toclevel3 {
+  margin-left: 4em;
+  font-size: 0.9em;
+}
+div.toclevel4 {
+  margin-left: 6em;
+  font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+div.tableblock > table {
+  border: 3px solid #527bbd;
+}
+thead, p.table.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.table {
+  margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+  border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+  border-left-style: none;
+  border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+  border-top-style: none;
+  border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+  margin-top: 1.0em;
+  margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+  font-weight: bold;
+  color: #527bbd;
+}
+p.tableblock {
+  margin-top: 0;
+}
+table.tableblock {
+  border-width: 3px;
+  border-spacing: 0px;
+  border-style: solid;
+  border-color: #527bbd;
+  border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+  border-width: 1px;
+  padding: 4px;
+  border-style: solid;
+  border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+  border-left-style: hidden;
+  border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+  border-top-style: hidden;
+  border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+  border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+  text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+  text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+  text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+  vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+  vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+  vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
+  border-top: 2px solid silver;
+  border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+  border-style: none;
+}
+body.manpage div.sectionbody {
+  margin-left: 3em;
+}
+
+@media print {
+  body.manpage div#toc { display: none; }
+}
+
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = {  // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+  function getText(el) {
+    var text = "";
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+        text += i.data;
+      else if (i.firstChild != null)
+        text += getText(i);
+    }
+    return text;
+  }
+
+  function TocEntry(el, text, toclevel) {
+    this.element = el;
+    this.text = text;
+    this.toclevel = toclevel;
+  }
+
+  function tocEntries(el, toclevels) {
+    var result = new Array;
+    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+    // Function that scans the DOM tree for header elements (the DOM2
+    // nodeIterator API would be a better technique but not supported by all
+    // browsers).
+    var iterate = function (el) {
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+          var mo = re.exec(i.tagName);
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+          }
+          iterate(i);
+        }
+      }
+    }
+    iterate(el);
+    return result;
+  }
+
+  var toc = document.getElementById("toc");
+  if (!toc) {
+    return;
+  }
+
+  // Delete existing TOC entries in case we're reloading the TOC.
+  var tocEntriesToRemove = [];
+  var i;
+  for (i = 0; i < toc.childNodes.length; i++) {
+    var entry = toc.childNodes[i];
+    if (entry.nodeName.toLowerCase() == 'div'
+     && entry.getAttribute("class")
+     && entry.getAttribute("class").match(/^toclevel/))
+      tocEntriesToRemove.push(entry);
+  }
+  for (i = 0; i < tocEntriesToRemove.length; i++) {
+    toc.removeChild(tocEntriesToRemove[i]);
+  }
+
+  // Rebuild TOC entries.
+  var entries = tocEntries(document.getElementById("content"), toclevels);
+  for (var i = 0; i < entries.length; ++i) {
+    var entry = entries[i];
+    if (entry.element.id == "")
+      entry.element.id = "_toc_" + i;
+    var a = document.createElement("a");
+    a.href = "#" + entry.element.id;
+    a.appendChild(document.createTextNode(entry.text));
+    var div = document.createElement("div");
+    div.appendChild(a);
+    div.className = "toclevel" + entry.toclevel;
+    toc.appendChild(div);
+  }
+  if (entries.length == 0)
+    toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+  // Delete existing footnote entries in case we're reloading the footnodes.
+  var i;
+  var noteholder = document.getElementById("footnotes");
+  if (!noteholder) {
+    return;
+  }
+  var entriesToRemove = [];
+  for (i = 0; i < noteholder.childNodes.length; i++) {
+    var entry = noteholder.childNodes[i];
+    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+      entriesToRemove.push(entry);
+  }
+  for (i = 0; i < entriesToRemove.length; i++) {
+    noteholder.removeChild(entriesToRemove[i]);
+  }
+
+  // Rebuild footnote entries.
+  var cont = document.getElementById("content");
+  var spans = cont.getElementsByTagName("span");
+  var refs = {};
+  var n = 0;
+  for (i=0; i<spans.length; i++) {
+    if (spans[i].className == "footnote") {
+      n++;
+      var note = spans[i].getAttribute("data-note");
+      if (!note) {
+        // Use [\s\S] in place of . so multi-line matches work.
+        // Because JavaScript has no s (dotall) regex flag.
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+        spans[i].innerHTML =
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+        spans[i].setAttribute("data-note", note);
+      }
+      noteholder.innerHTML +=
+        "<div class='footnote' id='_footnote_" + n + "'>" +
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+        n + "</a>. " + note + "</div>";
+      var id =spans[i].getAttribute("id");
+      if (id != null) refs["#"+id] = n;
+    }
+  }
+  if (n == 0)
+    noteholder.parentNode.removeChild(noteholder);
+  else {
+    // Process footnoterefs.
+    for (i=0; i<spans.length; i++) {
+      if (spans[i].className == "footnoteref") {
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+        href = href.match(/#.*/)[0];  // Because IE return full URL.
+        n = refs[href];
+        spans[i].innerHTML =
+          "[<a href='#_footnote_" + n +
+          "' title='View footnote' class='footnote'>" + n + "</a>]";
+      }
+    }
+  }
+},
+
+install: function(toclevels) {
+  var timerId;
+
+  function reinstall() {
+    asciidoc.footnotes();
+    if (toclevels) {
+      asciidoc.toc(toclevels);
+    }
+  }
+
+  function reinstallAndRemoveTimer() {
+    clearInterval(timerId);
+    reinstall();
+  }
+
+  timerId = setInterval(reinstall, 500);
+  if (document.addEventListener)
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+  else
+    window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install(2);
+/*]]>*/
+</script>
+</head>
+<body class="book">
+<div id="header">
+<h1>Vulkan on Android Implementor&#8217;s Guide</h1>
+<span id="revnumber">version 5</span>
+<div id="toc">
+  <div id="toctitle">Table of Contents</div>
+  <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph"><p>This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.</p></div>
+<div class="paragraph"><p>This is still a fairly rough draft; details will be filled in over time.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_architecture">1. Architecture</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The primary interface between Vulkan applications and a device&#8217;s Vulkan driver is the loader, which is part of AOSP and installed at <span class="monospaced">/system/lib[64]/libvulkan.so</span>. The loader provides the core Vulkan API entry points, as well as entry points of a few extensions that are required on Android and always present. In particular, the window system integration (WSI) extensions are exported by the loader and primarily implemented in it rather than the driver. The loader also supports enumerating and loading layers which can expose additional extensions and/or intercept core API calls on their way to the driver.</p></div>
+<div class="paragraph"><p>The NDK will include a stub <span class="monospaced">libvulkan.so</span> exporting the same symbols as the loader. Calling the Vulkan functions exported from <span class="monospaced">libvulkan.so</span> will enter trampoline functions in the loader which will dispatch to the appropriate layer or driver based on their first argument. The <span class="monospaced">vkGet*ProcAddr</span> calls will return the function pointers that the trampolines would dispatch to, so calling through these function pointers rather than the exported symbols will be slightly more efficient since it skips the trampoline and dispatch.</p></div>
+<div class="sect2">
+<h3 id="_driver_enumeration_and_loading">1.1. Driver Enumeration and Loading</h3>
+<div class="paragraph"><p>Android expects the GPUs available to the system to be known when the system image is built, so its driver enumeration process isn&#8217;t as elaborate as other platforms. The loader will use the existing HAL mechanism (see <a href="https://android.googlesource.com/platform/hardware/libhardware/+/lollipop-mr1-release/include/hardware/hardware.h">hardware.h</a>) for discovering and loading the driver. As of this writing, the preferred paths for 32-bit and 64-bit Vulkan drivers are:</p></div>
+<div class="literalblock">
+<div class="content monospaced">
+<pre>/vendor/lib/hw/vulkan.&lt;ro.product.platform&gt;.so
+/vendor/lib64/hw/vulkan.&lt;ro.product.platform&gt;.so</pre>
+</div></div>
+<div class="paragraph"><p>where <span class="monospaced">&lt;ro.product.platform&gt;</span> is replaced by the value of the system property of that name. See <a href="https://android.googlesource.com/platform/hardware/libhardware/+/lollipop-mr1-release/hardware.c">libhardware/hardware.c</a> for details and supported alternative locations.</p></div>
+<div class="paragraph"><p>The Vulkan <span class="monospaced">hw_module_t</span> derivative is currently trivial. If support for multiple drivers is ever added, the HAL module will export a list of strings that can be passed to the module <span class="monospaced">open</span> call. For the time being, only one driver is supported, and the constant string <span class="monospaced">HWVULKAN_DEVICE_0</span> is passed to <span class="monospaced">open</span>.</p></div>
+<div class="paragraph"><p>The Vulkan <span class="monospaced">hw_device_t</span> derivative corresponds to a single driver, though that driver can support multiple physical devices. The <span class="monospaced">hw_device_t</span> structure will be extended to export <span class="monospaced">vkGetGlobalExtensionProperties</span>, <span class="monospaced">vkCreateInstance</span>, and <span class="monospaced">vkGetInstanceProcAddr</span> functions. The loader will find all other <span class="monospaced">VkInstance</span>, <span class="monospaced">VkPhysicalDevice</span>, and <span class="monospaced">vkGetDeviceProcAddr</span> functions by calling <span class="monospaced">vkGetInstanceProcAddr</span>.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_layer_discovery_and_loading">1.2. Layer Discovery and Loading</h3>
+<div class="paragraph"><p>Android&#8217;s security model and policies differ significantly from other platforms. In particular, Android does not allow loading external code into a non-debuggable process on production (non-rooted) devices, nor does it allow external code to inspect or control the process&#8217;s memory/state/etc. This includes a prohibition on saving core dumps, API traces, etc. to disk for later inspection. So only layers delivered as part of the application will be enabled on production devices, and drivers must also not provide functionality that violates these policies.</p></div>
+<div class="paragraph"><p>There are three major use cases for layers:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+Development-time layers: validation layers, shims for tracing/profiling/debugging tools, etc. These shouldn&#8217;t be installed on the system image of production devices: they would be a waste of space for most users, and they should be updateable without requiring a system update. A developer wishing to use one of these during development has the ability to modify their application package (e.g. adding a file to their native libraries directory). IHV and OEM engineers who are trying to diagnose failures in shipping, unmodifiable apps are assumed to have access to non-production (rooted) builds of the system image.
+</p>
+</li>
+<li>
+<p>
+Utility layers, such as a layer that implements a heap for device memory. These layers will almost always expose extensions. Developers choose which layers, and which versions of those layers, to use in their application; different applications that use the same layer may still use different versions. Developers will choose which of these layers to ship in their application package.
+</p>
+</li>
+<li>
+<p>
+Injected layers, like framerate, social network, or game launcher overlays, which are provided by the user or some other application without the application&#8217;s knowledge or consent. These violate Android&#8217;s security policies and will not be supported.
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>In the normal state the loader will only search in the application&#8217;s native library directory for layers; details are TBD but it will probably just try to load any library with a name matching a particular pattern(e.g. <span class="monospaced">libvklayer_foo.so</span>). It will probably not need a separate manifest file; the developer deliberately included these layers, so the reasons to avoid loading libraries before enabling them don&#8217;t apply.</p></div>
+<div class="paragraph"><p>On debuggable devices (<span class="monospaced">ro.debuggable</span> property exists and is non-zero, generally rooted or engineering builds) or debuggable processes (<span class="monospaced">prctl(PR_GET_DUMPABLE)==1</span>, based on the application&#8217;s manifest), the loader may also search an adb-writeable location on /data for layers. It&#8217;s not clear whether this is useful; in all the cases it could be used, the layer could be just as easily be put in the application&#8217;s native library directory.</p></div>
+<div class="paragraph"><p>Finally, the loader may include a built-in validation layer that it will enable based on settings in the Developer Options menu, which would send validation errors or warnings to the system log. Drivers may be able to emit additional hardware-specific errors/warnings through this mechanism. This layer would not be enumerated through the API. This is intended to allow cooperative end-users to collect extra information about failures from unmodified applications on unmodified devices to aid triage/diagnosis of difficult-to-reproduce problems. The functionality would be intentionally limited to minimize security and privacy risk.</p></div>
+<div class="paragraph"><p>Our goal is to allow layers to be ported with only build-environment changes between Android and other platforms. This means the interface between layers and the loader must match the interface used by the LunarG loader. Currently, the LunarG interface has a few deficiencies and is largely unspecified. We intend to work with LunarG to correct as many deficiencies as we can and to specify the interface in detail so that layers can be implemented without referring to the loader source code.</p></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_window_system_integration">2. Window System Integration</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions will primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver&#8217;s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div>
+<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span>
+    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
+    <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
+    <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
+    <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
+<span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
+<div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt><span style="font-weight: bold"><span style="color: #0000FF">typedef</span></span> <span style="font-weight: bold"><span style="color: #0000FF">struct</span></span> <span style="color: #FF0000">{</span>
+    <span style="color: #008080">VkStructureType</span>             sType<span style="color: #990000">;</span> <span style="font-style: italic"><span style="color: #9A1900">// must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID</span></span>
+    <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> <span style="color: #009900">void</span><span style="color: #990000">*</span>                 pNext<span style="color: #990000">;</span>
+
+    <span style="font-style: italic"><span style="color: #9A1900">// Buffer handle and stride returned from gralloc alloc()</span></span>
+    <span style="color: #008080">buffer_handle_t</span>             handle<span style="color: #990000">;</span>
+    <span style="color: #009900">int</span>                         stride<span style="color: #990000">;</span>
+
+    <span style="font-style: italic"><span style="color: #9A1900">// Gralloc format and usage requested when the buffer was allocated.</span></span>
+    <span style="color: #009900">int</span>                         format<span style="color: #990000">;</span>
+    <span style="color: #009900">int</span>                         usage<span style="color: #990000">;</span>
+<span style="color: #FF0000">}</span> VkNativeBufferANDROID<span style="color: #990000">;</span></tt></pre></div></div>
+<div class="paragraph"><p>TBD: During swapchain re-creation (using <span class="monospaced">oldSwapChain</span>), we may have to defer allocation of new gralloc buffers until old buffers have been released. If so, the <span class="monospaced">vkCreateImage</span> calls will be deferred until the first <span class="monospaced">vkAcquireNextImageWSI</span> that would return the new image.</p></div>
+<div class="paragraph"><p>When creating a gralloc-backed image, the <span class="monospaced">VkImageCreateInfo</span> will have:</p></div>
+<div class="listingblock">
+<div class="content monospaced">
+<pre>  .imageType           = VK_IMAGE_TYPE_2D
+  .format              = a VkFormat matching the format requested for the gralloc buffer
+  .extent              = the 2D dimensions requested for the gralloc buffer
+  .mipLevels           = 1
+  .arraySize           = 1
+  .samples             = 1
+  .tiling              = VK_IMAGE_TILING_OPTIMAL
+  .usage               = VkSwapChainCreateInfoWSI::imageUsageFlags
+  .flags               = 0
+  .sharingMode         = VkSwapChainCreateInfoWSI::sharingMode
+  .queueFamilyCount    = VkSwapChainCreateInfoWSI::queueFamilyCount
+  .pQueueFamilyIndices = VkSwapChainCreateInfoWSI::pQueueFamilyIndices</pre>
+</div></div>
+<div class="paragraph"><p><span class="monospaced">vkAcquireImageANDROID</span> acquires ownership of a swapchain image and imports an
+externally-signalled native fence into both an existing VkSemaphore object
+and an existing VkFence object:</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkAcquireImageANDROID</span></span><span style="color: #990000">(</span>
+    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
+    <span style="color: #008080">VkImage</span>             image<span style="color: #990000">,</span>
+    <span style="color: #009900">int</span>                 nativeFenceFd<span style="color: #990000">,</span>
+    <span style="color: #008080">VkSemaphore</span>         semaphore<span style="color: #990000">,</span>
+    VkFence             fence
+<span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>This function is called during <span class="monospaced">vkAcquireNextImageWSI</span> to import a native
+fence into the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> objects provided by the
+application. Both semaphore and fence objects are optional in this call. The
+driver may also use this opportunity to recognize and handle any external
+changes to the gralloc buffer state; many drivers won&#8217;t need to do anything
+here. This call puts the <span class="monospaced">VkSemaphore</span> and <span class="monospaced">VkFence</span> into the same "pending"
+state as <span class="monospaced">vkQueueSignalSemaphore</span> and <span class="monospaced">vkQueueSubmit</span> respectively, so queues
+can wait on the semaphore and the application can wait on the fence. Both
+objects become signalled when the underlying native fence signals; if the
+native fence has already signalled, then the semaphore will be in the signalled
+state when this function returns. The driver takes ownership of the fence fd
+and is responsible for closing it when no longer needed. It must do so even if
+neither a semaphore or fence object is provided, or even if
+<span class="monospaced">vkAcquireImageANDROID</span> fails and returns an error. If <span class="monospaced">fenceFd</span> is -1, it
+is as if the native fence was already signalled.</p></div>
+<div class="paragraph"><p><span class="monospaced">vkQueueSignalReleaseImageANDROID</span> prepares a swapchain image for external use, and creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkQueueSignalReleaseImageANDROID</span></span><span style="color: #990000">(</span>
+    <span style="color: #008080">VkQueue</span>             queue<span style="color: #990000">,</span>
+    <span style="color: #008080">uint32_t</span>            waitSemaphoreCount<span style="color: #990000">,</span>
+    <span style="font-weight: bold"><span style="color: #0000FF">const</span></span> VkSemaphore<span style="color: #990000">*</span>  pWaitSemaphores<span style="color: #990000">,</span>
+    <span style="color: #008080">VkImage</span>             image<span style="color: #990000">,</span>
+    <span style="color: #009900">int</span><span style="color: #990000">*</span>                pNativeFenceFd
+<span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>This will be called during <span class="monospaced">vkQueuePresentWSI</span> on the provided queue. Effects are similar to <span class="monospaced">vkQueueSignalSemaphore</span>, except with a native fence instead of a semaphore. The native fence must: not signal until the <span class="monospaced">waitSemaphoreCount</span> semaphores in <span class="monospaced">pWaitSemaphores</span> have signaled. Unlike <span class="monospaced">vkQueueSignalSemaphore</span>, however, this call creates and returns the synchronization object that will be signalled rather than having it provided as input. If the queue is already idle when this function is called, it is allowed but not required to set <span class="monospaced">*pNativeFenceFd</span> to -1. The file descriptor returned in <span class="monospaced">*pNativeFenceFd</span> is owned and will be closed by the caller. Many drivers will be able to ignore the <span class="monospaced">image</span> parameter, but some may need to prepare CPU-side data structures associated with a gralloc buffer for use by external image consumers. Preparing buffer contents for use by external consumers should have been done asynchronously as part of transitioning the image to <span class="monospaced">VK_IMAGE_LAYOUT_PRESENT_SRC_KHR</span>.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_history">3. History</h2>
+<div class="sectionbody">
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+<strong>2015-07-08</strong> Initial version
+</p>
+</li>
+<li>
+<p>
+<strong>2015-08-16</strong>
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Renamed to Implementor&#8217;s Guide
+</p>
+</li>
+<li>
+<p>
+Wording and formatting changes
+</p>
+</li>
+<li>
+<p>
+Updated based on resolution of Khronos bug 14265
+</p>
+</li>
+<li>
+<p>
+Deferred support for multiple drivers
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+<strong>2015-11-04</strong>
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added vkGetSwapchainGrallocUsageANDROID
+</p>
+</li>
+<li>
+<p>
+Replaced vkImportNativeFenceANDROID and vkQueueSignalNativeFenceANDROID
+     with vkAcquireImageANDROID and vkQueueSignalReleaseImageANDROID, to allow
+     drivers to known the ownership state of swapchain images.
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+<strong>2015-12-03</strong>
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added a VkFence parameter to vkAcquireImageANDROID corresponding to the
+     parameter added to vkAcquireNextImageKHR.
+</p>
+</li>
+</ul></div>
+</li>
+<li>
+<p>
+<strong>2016-01-08</strong>
+</p>
+<div class="ulist"><ul>
+<li>
+<p>
+Added waitSemaphoreCount and pWaitSemaphores parameters to vkQueueSignalReleaseImageANDROID.
+</p>
+</li>
+</ul></div>
+</li>
+</ol></div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr></div>
+<div id="footer">
+<div id="footer-text">
+Version 5<br>
+Last updated 2016-01-08 22:43:07 PST
+</div>
+</div>
+</body>
+</html>
diff --git a/vulkan/include/hardware/hwvulkan.h b/vulkan/include/hardware/hwvulkan.h
new file mode 100644
index 0000000..9e9a14d
--- /dev/null
+++ b/vulkan/include/hardware/hwvulkan.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_HWVULKAN_H
+#define ANDROID_HWVULKAN_H
+
+#include <hardware/hardware.h>
+#include <vulkan/vulkan.h>
+
+__BEGIN_DECLS
+
+#define HWVULKAN_HARDWARE_MODULE_ID "vulkan"
+
+#define HWVULKAN_MODULE_API_VERSION_0_1 HARDWARE_MODULE_API_VERSION(0, 1)
+#define HWVULKAN_DEVICE_API_VERSION_0_1 HARDWARE_DEVICE_API_VERSION_2(0, 1, 0)
+
+#define HWVULKAN_DEVICE_0 "vk0"
+
+typedef struct hwvulkan_module_t {
+    struct hw_module_t common;
+} hwvulkan_module_t;
+
+/* Dispatchable Vulkan object handles must be pointers, which must point to
+ * instances of hwvulkan_dispatch_t (potentially followed by additional
+ * implementation-defined data). On return from the creation function, the
+ * 'magic' field must contain HWVULKAN_DISPATCH_MAGIC; the loader will overwrite
+ * the 'vtbl' field.
+ *
+ * NOTE: The magic value and the layout of hwvulkan_dispatch_t match the LunarG
+ * loader used on platforms, to avoid pointless annoying differences for
+ * multi-platform drivers. Don't change them without a good reason. If there is
+ * an opportunity to change it, using a magic value that doesn't leave the
+ * upper 32-bits zero on 64-bit platforms would be nice.
+ */
+#define HWVULKAN_DISPATCH_MAGIC 0x01CDC0DE
+typedef union {
+    uintptr_t magic;
+    const void* vtbl;
+} hwvulkan_dispatch_t;
+
+/* A hwvulkan_device_t corresponds to an ICD on other systems. Currently there
+ * can only be one on a system (HWVULKAN_DEVICE_0). It is opened once per
+ * process when the Vulkan API is first used; the hw_device_t::close() function
+ * is never called. Any non-trivial resource allocation should be done when
+ * the VkInstance is created rather than when the hwvulkan_device_t is opened.
+ */
+typedef struct hwvulkan_device_t {
+    struct hw_device_t common;
+
+    PFN_vkEnumerateInstanceExtensionProperties
+        EnumerateInstanceExtensionProperties;
+    PFN_vkCreateInstance CreateInstance;
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+} hwvulkan_device_t;
+
+__END_DECLS
+
+#endif  // ANDROID_HWVULKAN_H
diff --git a/vulkan/include/vulkan/vk_android_native_buffer.h b/vulkan/include/vulkan/vk_android_native_buffer.h
new file mode 100644
index 0000000..d0ebf81
--- /dev/null
+++ b/vulkan/include/vulkan/vk_android_native_buffer.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef __VK_ANDROID_NATIVE_BUFFER_H__
+#define __VK_ANDROID_NATIVE_BUFFER_H__
+
+#include <system/window.h>
+#include <vulkan/vulkan.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define VK_ANDROID_native_buffer 1
+
+#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER 11
+#define VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION     5
+#define VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME   "VK_ANDROID_native_buffer"
+
+#define VK_ANDROID_NATIVE_BUFFER_ENUM(type,id)    ((type)(1000000000 + (1000 * (VK_ANDROID_NATIVE_BUFFER_EXTENSION_NUMBER - 1)) + (id)))
+#define VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID   VK_ANDROID_NATIVE_BUFFER_ENUM(VkStructureType, 0)
+
+typedef struct {
+    VkStructureType             sType; // must be VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID
+    const void*                 pNext;
+
+    // Buffer handle and stride returned from gralloc alloc()
+    buffer_handle_t             handle;
+    int                         stride;
+
+    // Gralloc format and usage requested when the buffer was allocated.
+    int                         format;
+    int                         usage;
+} VkNativeBufferANDROID;
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageANDROID)(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageANDROID)(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsageANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
+    int*                grallocUsage
+);
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageANDROID(
+    VkDevice            device,
+    VkImage             image,
+    int                 nativeFenceFd,
+    VkSemaphore         semaphore,
+    VkFence             fence
+);
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageANDROID(
+    VkQueue             queue,
+    uint32_t            waitSemaphoreCount,
+    const VkSemaphore*  pWaitSemaphores,
+    VkImage             image,
+    int*                pNativeFenceFd
+);
+// -- DEPRECATED --
+VKAPI_ATTR VkResult VKAPI_CALL vkImportNativeFenceANDROID(
+    VkDevice            device,
+    VkSemaphore         semaphore,
+    int                 nativeFenceFd
+);
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalNativeFenceANDROID(
+    VkQueue             queue,
+    int*                pNativeFenceFd
+);
+// ----------------
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __VK_ANDROID_NATIVE_BUFFER_H__
diff --git a/vulkan/include/vulkan/vk_layer_interface.h b/vulkan/include/vulkan/vk_layer_interface.h
new file mode 100644
index 0000000..f2a5232
--- /dev/null
+++ b/vulkan/include/vulkan/vk_layer_interface.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ * Copyright (c) 2016 Google Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and/or associated documentation files (the "Materials"), to
+ * deal in the Materials without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Materials, and to permit persons to whom the Materials are
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice(s) and this permission notice shall be included in
+ * all copies or substantial portions of the Materials.
+ *
+ * THE MATERIALS ARE 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 MATERIALS OR THE
+ * USE OR OTHER DEALINGS IN THE MATERIALS.
+ *
+ */
+#pragma once
+
+#include <vulkan/vulkan.h>
+
+// ------------------------------------------------------------------------------------------------
+// CreateInstance and CreateDevice support structures
+
+typedef enum VkLayerFunction_ {
+    VK_LAYER_FUNCTION_LINK = 0,
+    VK_LAYER_FUNCTION_DATA_CALLBACK = 1
+} VkLayerFunction;
+
+typedef struct VkLayerInstanceLink_ {
+    struct VkLayerInstanceLink_* pNext;
+    PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+} VkLayerInstanceLink;
+
+typedef VkResult(VKAPI_PTR* PFN_vkSetInstanceLoaderData)(VkInstance instance,
+                                                         void* object);
+typedef VkResult(VKAPI_PTR* PFN_vkSetDeviceLoaderData)(VkDevice device,
+                                                       void* object);
+
+typedef struct {
+    VkStructureType sType;  // VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO
+    const void* pNext;
+    VkLayerFunction function;
+    union {
+        VkLayerInstanceLink* pLayerInfo;
+        PFN_vkSetInstanceLoaderData pfnSetInstanceLoaderData;
+    } u;
+} VkLayerInstanceCreateInfo;
+
+typedef struct VkLayerDeviceLink_ {
+    struct VkLayerDeviceLink_* pNext;
+    PFN_vkGetInstanceProcAddr pfnNextGetInstanceProcAddr;
+    PFN_vkGetDeviceProcAddr pfnNextGetDeviceProcAddr;
+} VkLayerDeviceLink;
+
+typedef struct {
+    VkStructureType sType;  // VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO
+    const void* pNext;
+    VkLayerFunction function;
+    union {
+        VkLayerDeviceLink* pLayerInfo;
+        PFN_vkSetDeviceLoaderData pfnSetDeviceLoaderData;
+    } u;
+} VkLayerDeviceCreateInfo;
diff --git a/vulkan/include/vulkan/vk_platform.h b/vulkan/include/vulkan/vk_platform.h
new file mode 100644
index 0000000..a53e725
--- /dev/null
+++ b/vulkan/include/vulkan/vk_platform.h
@@ -0,0 +1,127 @@
+//
+// File: vk_platform.h
+//
+/*
+** Copyright (c) 2014-2015 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+
+#ifndef __VK_PLATFORM_H__
+#define __VK_PLATFORM_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*
+***************************************************************************************************
+*   Platform-specific directives and type declarations
+***************************************************************************************************
+*/
+
+/* Platform-specific calling convention macros.
+ *
+ * Platforms should define these so that Vulkan clients call Vulkan commands
+ * with the same calling conventions that the Vulkan implementation expects.
+ *
+ * VKAPI_ATTR - Placed before the return type in function declarations.
+ *              Useful for C++11 and GCC/Clang-style function attribute syntax.
+ * VKAPI_CALL - Placed after the return type in function declarations.
+ *              Useful for MSVC-style calling convention syntax.
+ * VKAPI_PTR  - Placed between the '(' and '*' in function pointer types.
+ *
+ * Function declaration:  VKAPI_ATTR void VKAPI_CALL vkCommand(void);
+ * Function pointer type: typedef void (VKAPI_PTR *PFN_vkCommand)(void);
+ */
+#if defined(_WIN32)
+    // On Windows, Vulkan commands use the stdcall convention
+    #define VKAPI_ATTR
+    #define VKAPI_CALL __stdcall
+    #define VKAPI_PTR  VKAPI_CALL
+#elif defined(__ANDROID__) && defined(__ARM_EABI__) && !defined(__ARM_ARCH_7A__)
+    // Android does not support Vulkan in native code using the "armeabi" ABI.
+    #error "Vulkan requires the 'armeabi-v7a' or 'armeabi-v7a-hard' ABI on 32-bit ARM CPUs"
+#elif defined(__ANDROID__) && defined(__ARM_ARCH_7A__)
+    // On Android/ARMv7a, Vulkan functions use the armeabi-v7a-hard calling
+    // convention, even if the application's native code is compiled with the
+    // armeabi-v7a calling convention.
+    #define VKAPI_ATTR __attribute__((pcs("aapcs-vfp")))
+    #define VKAPI_CALL
+    #define VKAPI_PTR  VKAPI_ATTR
+#else
+    // On other platforms, use the default calling convention
+    #define VKAPI_ATTR
+    #define VKAPI_CALL
+    #define VKAPI_PTR
+#endif
+
+#include <stddef.h>
+
+#if !defined(VK_NO_STDINT_H)
+    #if defined(_MSC_VER) && (_MSC_VER < 1600)
+        typedef signed   __int8  int8_t;
+        typedef unsigned __int8  uint8_t;
+        typedef signed   __int16 int16_t;
+        typedef unsigned __int16 uint16_t;
+        typedef signed   __int32 int32_t;
+        typedef unsigned __int32 uint32_t;
+        typedef signed   __int64 int64_t;
+        typedef unsigned __int64 uint64_t;
+    #else
+        #include <stdint.h>
+    #endif
+#endif // !defined(VK_NO_STDINT_H)
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+// Platform-specific headers required by platform window system extensions.
+// These are enabled prior to #including "vulkan.h". The same enable then
+// controls inclusion of the extension interfaces in vulkan.h.
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+#include <android/native_window.h>
+#endif
+
+#ifdef VK_USE_PLATFORM_MIR_KHR
+#include <mir_toolkit/client_types.h>
+#endif
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+#include <wayland-client.h>
+#endif
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#include <windows.h>
+#endif
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+#include <X11/Xlib.h>
+#endif
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+#include <xcb/xcb.h>
+#endif
+
+#endif // __VK_PLATFORM_H__
diff --git a/vulkan/include/vulkan/vulkan.h b/vulkan/include/vulkan/vulkan.h
new file mode 100644
index 0000000..cd6a71a
--- /dev/null
+++ b/vulkan/include/vulkan/vulkan.h
@@ -0,0 +1,3775 @@
+#ifndef __vulkan_h_
+#define __vulkan_h_ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** Copyright (c) 2015-2016 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are 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 Materials.
+**
+** THE MATERIALS ARE 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
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/*
+** This header is generated from the Khronos Vulkan XML API Registry.
+**
+*/
+
+
+#define VK_VERSION_1_0 1
+#include "vk_platform.h"
+
+#define VK_MAKE_VERSION(major, minor, patch) \
+    (((major) << 22) | ((minor) << 12) | (patch))
+
+// Vulkan API version supported by this file
+#define VK_API_VERSION VK_MAKE_VERSION(1, 0, 3)
+
+#define VK_VERSION_MAJOR(version) ((uint32_t)(version) >> 22)
+#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
+#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
+
+#define VK_NULL_HANDLE 0
+        
+
+
+#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
+
+
+#if defined(__LP64__) || defined(_WIN64) || defined(__x86_64__) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+        #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
+#else
+        #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#endif
+        
+
+
+typedef uint32_t VkFlags;
+typedef uint32_t VkBool32;
+typedef uint64_t VkDeviceSize;
+typedef uint32_t VkSampleMask;
+
+VK_DEFINE_HANDLE(VkInstance)
+VK_DEFINE_HANDLE(VkPhysicalDevice)
+VK_DEFINE_HANDLE(VkDevice)
+VK_DEFINE_HANDLE(VkQueue)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSemaphore)
+VK_DEFINE_HANDLE(VkCommandBuffer)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFence)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDeviceMemory)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBuffer)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImage)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkEvent)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkQueryPool)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkBufferView)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkImageView)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkShaderModule)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineLayout)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkRenderPass)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipeline)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSetLayout)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSampler)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorPool)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDescriptorSet)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkFramebuffer)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkCommandPool)
+
+#define VK_LOD_CLAMP_NONE                 1000.0f
+#define VK_REMAINING_MIP_LEVELS           (~0U)
+#define VK_REMAINING_ARRAY_LAYERS         (~0U)
+#define VK_WHOLE_SIZE                     (~0ULL)
+#define VK_ATTACHMENT_UNUSED              (~0U)
+#define VK_TRUE                           1
+#define VK_FALSE                          0
+#define VK_QUEUE_FAMILY_IGNORED           (~0U)
+#define VK_SUBPASS_EXTERNAL               (~0U)
+#define VK_MAX_PHYSICAL_DEVICE_NAME_SIZE  256
+#define VK_UUID_SIZE                      16
+#define VK_MAX_MEMORY_TYPES               32
+#define VK_MAX_MEMORY_HEAPS               16
+#define VK_MAX_EXTENSION_NAME_SIZE        256
+#define VK_MAX_DESCRIPTION_SIZE           256
+
+
+typedef enum VkPipelineCacheHeaderVersion {
+    VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1,
+    VK_PIPELINE_CACHE_HEADER_VERSION_BEGIN_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
+    VK_PIPELINE_CACHE_HEADER_VERSION_END_RANGE = VK_PIPELINE_CACHE_HEADER_VERSION_ONE,
+    VK_PIPELINE_CACHE_HEADER_VERSION_RANGE_SIZE = (VK_PIPELINE_CACHE_HEADER_VERSION_ONE - VK_PIPELINE_CACHE_HEADER_VERSION_ONE + 1),
+    VK_PIPELINE_CACHE_HEADER_VERSION_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineCacheHeaderVersion;
+
+typedef enum VkResult {
+    VK_SUCCESS = 0,
+    VK_NOT_READY = 1,
+    VK_TIMEOUT = 2,
+    VK_EVENT_SET = 3,
+    VK_EVENT_RESET = 4,
+    VK_INCOMPLETE = 5,
+    VK_ERROR_OUT_OF_HOST_MEMORY = -1,
+    VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
+    VK_ERROR_INITIALIZATION_FAILED = -3,
+    VK_ERROR_DEVICE_LOST = -4,
+    VK_ERROR_MEMORY_MAP_FAILED = -5,
+    VK_ERROR_LAYER_NOT_PRESENT = -6,
+    VK_ERROR_EXTENSION_NOT_PRESENT = -7,
+    VK_ERROR_FEATURE_NOT_PRESENT = -8,
+    VK_ERROR_INCOMPATIBLE_DRIVER = -9,
+    VK_ERROR_TOO_MANY_OBJECTS = -10,
+    VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
+    VK_ERROR_SURFACE_LOST_KHR = -1000000000,
+    VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
+    VK_SUBOPTIMAL_KHR = 1000001003,
+    VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
+    VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
+    VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
+    VK_RESULT_BEGIN_RANGE = VK_ERROR_FORMAT_NOT_SUPPORTED,
+    VK_RESULT_END_RANGE = VK_INCOMPLETE,
+    VK_RESULT_RANGE_SIZE = (VK_INCOMPLETE - VK_ERROR_FORMAT_NOT_SUPPORTED + 1),
+    VK_RESULT_MAX_ENUM = 0x7FFFFFFF
+} VkResult;
+
+typedef enum VkStructureType {
+    VK_STRUCTURE_TYPE_APPLICATION_INFO = 0,
+    VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1,
+    VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2,
+    VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3,
+    VK_STRUCTURE_TYPE_SUBMIT_INFO = 4,
+    VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO = 5,
+    VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE = 6,
+    VK_STRUCTURE_TYPE_BIND_SPARSE_INFO = 7,
+    VK_STRUCTURE_TYPE_FENCE_CREATE_INFO = 8,
+    VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO = 9,
+    VK_STRUCTURE_TYPE_EVENT_CREATE_INFO = 10,
+    VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO = 11,
+    VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO = 12,
+    VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO = 13,
+    VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO = 14,
+    VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO = 15,
+    VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO = 16,
+    VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO = 17,
+    VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO = 18,
+    VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO = 19,
+    VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO = 20,
+    VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO = 21,
+    VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO = 22,
+    VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO = 23,
+    VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO = 24,
+    VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO = 25,
+    VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO = 26,
+    VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO = 27,
+    VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO = 28,
+    VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO = 29,
+    VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO = 30,
+    VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO = 31,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO = 32,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO = 33,
+    VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO = 34,
+    VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET = 35,
+    VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET = 36,
+    VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO = 37,
+    VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO = 38,
+    VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO = 39,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO = 40,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO = 41,
+    VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO = 42,
+    VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO = 43,
+    VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER = 44,
+    VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER = 45,
+    VK_STRUCTURE_TYPE_MEMORY_BARRIER = 46,
+    VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO = 47,
+    VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO = 48,
+    VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR = 1000001000,
+    VK_STRUCTURE_TYPE_PRESENT_INFO_KHR = 1000001001,
+    VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR = 1000002000,
+    VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR = 1000002001,
+    VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR = 1000003000,
+    VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
+    VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
+    VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
+    VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
+    VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR = 1000008000,
+    VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+    VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT = 1000011000,
+    VK_STRUCTURE_TYPE_BEGIN_RANGE = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+    VK_STRUCTURE_TYPE_END_RANGE = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO,
+    VK_STRUCTURE_TYPE_RANGE_SIZE = (VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO - VK_STRUCTURE_TYPE_APPLICATION_INFO + 1),
+    VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkStructureType;
+
+typedef enum VkSystemAllocationScope {
+    VK_SYSTEM_ALLOCATION_SCOPE_COMMAND = 0,
+    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT = 1,
+    VK_SYSTEM_ALLOCATION_SCOPE_CACHE = 2,
+    VK_SYSTEM_ALLOCATION_SCOPE_DEVICE = 3,
+    VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE = 4,
+    VK_SYSTEM_ALLOCATION_SCOPE_BEGIN_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_COMMAND,
+    VK_SYSTEM_ALLOCATION_SCOPE_END_RANGE = VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE,
+    VK_SYSTEM_ALLOCATION_SCOPE_RANGE_SIZE = (VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND + 1),
+    VK_SYSTEM_ALLOCATION_SCOPE_MAX_ENUM = 0x7FFFFFFF
+} VkSystemAllocationScope;
+
+typedef enum VkInternalAllocationType {
+    VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE = 0,
+    VK_INTERNAL_ALLOCATION_TYPE_BEGIN_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE,
+    VK_INTERNAL_ALLOCATION_TYPE_END_RANGE = VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE,
+    VK_INTERNAL_ALLOCATION_TYPE_RANGE_SIZE = (VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE - VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE + 1),
+    VK_INTERNAL_ALLOCATION_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkInternalAllocationType;
+
+typedef enum VkFormat {
+    VK_FORMAT_UNDEFINED = 0,
+    VK_FORMAT_R4G4_UNORM_PACK8 = 1,
+    VK_FORMAT_R4G4B4A4_UNORM_PACK16 = 2,
+    VK_FORMAT_B4G4R4A4_UNORM_PACK16 = 3,
+    VK_FORMAT_R5G6B5_UNORM_PACK16 = 4,
+    VK_FORMAT_B5G6R5_UNORM_PACK16 = 5,
+    VK_FORMAT_R5G5B5A1_UNORM_PACK16 = 6,
+    VK_FORMAT_B5G5R5A1_UNORM_PACK16 = 7,
+    VK_FORMAT_A1R5G5B5_UNORM_PACK16 = 8,
+    VK_FORMAT_R8_UNORM = 9,
+    VK_FORMAT_R8_SNORM = 10,
+    VK_FORMAT_R8_USCALED = 11,
+    VK_FORMAT_R8_SSCALED = 12,
+    VK_FORMAT_R8_UINT = 13,
+    VK_FORMAT_R8_SINT = 14,
+    VK_FORMAT_R8_SRGB = 15,
+    VK_FORMAT_R8G8_UNORM = 16,
+    VK_FORMAT_R8G8_SNORM = 17,
+    VK_FORMAT_R8G8_USCALED = 18,
+    VK_FORMAT_R8G8_SSCALED = 19,
+    VK_FORMAT_R8G8_UINT = 20,
+    VK_FORMAT_R8G8_SINT = 21,
+    VK_FORMAT_R8G8_SRGB = 22,
+    VK_FORMAT_R8G8B8_UNORM = 23,
+    VK_FORMAT_R8G8B8_SNORM = 24,
+    VK_FORMAT_R8G8B8_USCALED = 25,
+    VK_FORMAT_R8G8B8_SSCALED = 26,
+    VK_FORMAT_R8G8B8_UINT = 27,
+    VK_FORMAT_R8G8B8_SINT = 28,
+    VK_FORMAT_R8G8B8_SRGB = 29,
+    VK_FORMAT_B8G8R8_UNORM = 30,
+    VK_FORMAT_B8G8R8_SNORM = 31,
+    VK_FORMAT_B8G8R8_USCALED = 32,
+    VK_FORMAT_B8G8R8_SSCALED = 33,
+    VK_FORMAT_B8G8R8_UINT = 34,
+    VK_FORMAT_B8G8R8_SINT = 35,
+    VK_FORMAT_B8G8R8_SRGB = 36,
+    VK_FORMAT_R8G8B8A8_UNORM = 37,
+    VK_FORMAT_R8G8B8A8_SNORM = 38,
+    VK_FORMAT_R8G8B8A8_USCALED = 39,
+    VK_FORMAT_R8G8B8A8_SSCALED = 40,
+    VK_FORMAT_R8G8B8A8_UINT = 41,
+    VK_FORMAT_R8G8B8A8_SINT = 42,
+    VK_FORMAT_R8G8B8A8_SRGB = 43,
+    VK_FORMAT_B8G8R8A8_UNORM = 44,
+    VK_FORMAT_B8G8R8A8_SNORM = 45,
+    VK_FORMAT_B8G8R8A8_USCALED = 46,
+    VK_FORMAT_B8G8R8A8_SSCALED = 47,
+    VK_FORMAT_B8G8R8A8_UINT = 48,
+    VK_FORMAT_B8G8R8A8_SINT = 49,
+    VK_FORMAT_B8G8R8A8_SRGB = 50,
+    VK_FORMAT_A8B8G8R8_UNORM_PACK32 = 51,
+    VK_FORMAT_A8B8G8R8_SNORM_PACK32 = 52,
+    VK_FORMAT_A8B8G8R8_USCALED_PACK32 = 53,
+    VK_FORMAT_A8B8G8R8_SSCALED_PACK32 = 54,
+    VK_FORMAT_A8B8G8R8_UINT_PACK32 = 55,
+    VK_FORMAT_A8B8G8R8_SINT_PACK32 = 56,
+    VK_FORMAT_A8B8G8R8_SRGB_PACK32 = 57,
+    VK_FORMAT_A2R10G10B10_UNORM_PACK32 = 58,
+    VK_FORMAT_A2R10G10B10_SNORM_PACK32 = 59,
+    VK_FORMAT_A2R10G10B10_USCALED_PACK32 = 60,
+    VK_FORMAT_A2R10G10B10_SSCALED_PACK32 = 61,
+    VK_FORMAT_A2R10G10B10_UINT_PACK32 = 62,
+    VK_FORMAT_A2R10G10B10_SINT_PACK32 = 63,
+    VK_FORMAT_A2B10G10R10_UNORM_PACK32 = 64,
+    VK_FORMAT_A2B10G10R10_SNORM_PACK32 = 65,
+    VK_FORMAT_A2B10G10R10_USCALED_PACK32 = 66,
+    VK_FORMAT_A2B10G10R10_SSCALED_PACK32 = 67,
+    VK_FORMAT_A2B10G10R10_UINT_PACK32 = 68,
+    VK_FORMAT_A2B10G10R10_SINT_PACK32 = 69,
+    VK_FORMAT_R16_UNORM = 70,
+    VK_FORMAT_R16_SNORM = 71,
+    VK_FORMAT_R16_USCALED = 72,
+    VK_FORMAT_R16_SSCALED = 73,
+    VK_FORMAT_R16_UINT = 74,
+    VK_FORMAT_R16_SINT = 75,
+    VK_FORMAT_R16_SFLOAT = 76,
+    VK_FORMAT_R16G16_UNORM = 77,
+    VK_FORMAT_R16G16_SNORM = 78,
+    VK_FORMAT_R16G16_USCALED = 79,
+    VK_FORMAT_R16G16_SSCALED = 80,
+    VK_FORMAT_R16G16_UINT = 81,
+    VK_FORMAT_R16G16_SINT = 82,
+    VK_FORMAT_R16G16_SFLOAT = 83,
+    VK_FORMAT_R16G16B16_UNORM = 84,
+    VK_FORMAT_R16G16B16_SNORM = 85,
+    VK_FORMAT_R16G16B16_USCALED = 86,
+    VK_FORMAT_R16G16B16_SSCALED = 87,
+    VK_FORMAT_R16G16B16_UINT = 88,
+    VK_FORMAT_R16G16B16_SINT = 89,
+    VK_FORMAT_R16G16B16_SFLOAT = 90,
+    VK_FORMAT_R16G16B16A16_UNORM = 91,
+    VK_FORMAT_R16G16B16A16_SNORM = 92,
+    VK_FORMAT_R16G16B16A16_USCALED = 93,
+    VK_FORMAT_R16G16B16A16_SSCALED = 94,
+    VK_FORMAT_R16G16B16A16_UINT = 95,
+    VK_FORMAT_R16G16B16A16_SINT = 96,
+    VK_FORMAT_R16G16B16A16_SFLOAT = 97,
+    VK_FORMAT_R32_UINT = 98,
+    VK_FORMAT_R32_SINT = 99,
+    VK_FORMAT_R32_SFLOAT = 100,
+    VK_FORMAT_R32G32_UINT = 101,
+    VK_FORMAT_R32G32_SINT = 102,
+    VK_FORMAT_R32G32_SFLOAT = 103,
+    VK_FORMAT_R32G32B32_UINT = 104,
+    VK_FORMAT_R32G32B32_SINT = 105,
+    VK_FORMAT_R32G32B32_SFLOAT = 106,
+    VK_FORMAT_R32G32B32A32_UINT = 107,
+    VK_FORMAT_R32G32B32A32_SINT = 108,
+    VK_FORMAT_R32G32B32A32_SFLOAT = 109,
+    VK_FORMAT_R64_UINT = 110,
+    VK_FORMAT_R64_SINT = 111,
+    VK_FORMAT_R64_SFLOAT = 112,
+    VK_FORMAT_R64G64_UINT = 113,
+    VK_FORMAT_R64G64_SINT = 114,
+    VK_FORMAT_R64G64_SFLOAT = 115,
+    VK_FORMAT_R64G64B64_UINT = 116,
+    VK_FORMAT_R64G64B64_SINT = 117,
+    VK_FORMAT_R64G64B64_SFLOAT = 118,
+    VK_FORMAT_R64G64B64A64_UINT = 119,
+    VK_FORMAT_R64G64B64A64_SINT = 120,
+    VK_FORMAT_R64G64B64A64_SFLOAT = 121,
+    VK_FORMAT_B10G11R11_UFLOAT_PACK32 = 122,
+    VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 = 123,
+    VK_FORMAT_D16_UNORM = 124,
+    VK_FORMAT_X8_D24_UNORM_PACK32 = 125,
+    VK_FORMAT_D32_SFLOAT = 126,
+    VK_FORMAT_S8_UINT = 127,
+    VK_FORMAT_D16_UNORM_S8_UINT = 128,
+    VK_FORMAT_D24_UNORM_S8_UINT = 129,
+    VK_FORMAT_D32_SFLOAT_S8_UINT = 130,
+    VK_FORMAT_BC1_RGB_UNORM_BLOCK = 131,
+    VK_FORMAT_BC1_RGB_SRGB_BLOCK = 132,
+    VK_FORMAT_BC1_RGBA_UNORM_BLOCK = 133,
+    VK_FORMAT_BC1_RGBA_SRGB_BLOCK = 134,
+    VK_FORMAT_BC2_UNORM_BLOCK = 135,
+    VK_FORMAT_BC2_SRGB_BLOCK = 136,
+    VK_FORMAT_BC3_UNORM_BLOCK = 137,
+    VK_FORMAT_BC3_SRGB_BLOCK = 138,
+    VK_FORMAT_BC4_UNORM_BLOCK = 139,
+    VK_FORMAT_BC4_SNORM_BLOCK = 140,
+    VK_FORMAT_BC5_UNORM_BLOCK = 141,
+    VK_FORMAT_BC5_SNORM_BLOCK = 142,
+    VK_FORMAT_BC6H_UFLOAT_BLOCK = 143,
+    VK_FORMAT_BC6H_SFLOAT_BLOCK = 144,
+    VK_FORMAT_BC7_UNORM_BLOCK = 145,
+    VK_FORMAT_BC7_SRGB_BLOCK = 146,
+    VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147,
+    VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK = 148,
+    VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK = 149,
+    VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK = 150,
+    VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK = 151,
+    VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK = 152,
+    VK_FORMAT_EAC_R11_UNORM_BLOCK = 153,
+    VK_FORMAT_EAC_R11_SNORM_BLOCK = 154,
+    VK_FORMAT_EAC_R11G11_UNORM_BLOCK = 155,
+    VK_FORMAT_EAC_R11G11_SNORM_BLOCK = 156,
+    VK_FORMAT_ASTC_4x4_UNORM_BLOCK = 157,
+    VK_FORMAT_ASTC_4x4_SRGB_BLOCK = 158,
+    VK_FORMAT_ASTC_5x4_UNORM_BLOCK = 159,
+    VK_FORMAT_ASTC_5x4_SRGB_BLOCK = 160,
+    VK_FORMAT_ASTC_5x5_UNORM_BLOCK = 161,
+    VK_FORMAT_ASTC_5x5_SRGB_BLOCK = 162,
+    VK_FORMAT_ASTC_6x5_UNORM_BLOCK = 163,
+    VK_FORMAT_ASTC_6x5_SRGB_BLOCK = 164,
+    VK_FORMAT_ASTC_6x6_UNORM_BLOCK = 165,
+    VK_FORMAT_ASTC_6x6_SRGB_BLOCK = 166,
+    VK_FORMAT_ASTC_8x5_UNORM_BLOCK = 167,
+    VK_FORMAT_ASTC_8x5_SRGB_BLOCK = 168,
+    VK_FORMAT_ASTC_8x6_UNORM_BLOCK = 169,
+    VK_FORMAT_ASTC_8x6_SRGB_BLOCK = 170,
+    VK_FORMAT_ASTC_8x8_UNORM_BLOCK = 171,
+    VK_FORMAT_ASTC_8x8_SRGB_BLOCK = 172,
+    VK_FORMAT_ASTC_10x5_UNORM_BLOCK = 173,
+    VK_FORMAT_ASTC_10x5_SRGB_BLOCK = 174,
+    VK_FORMAT_ASTC_10x6_UNORM_BLOCK = 175,
+    VK_FORMAT_ASTC_10x6_SRGB_BLOCK = 176,
+    VK_FORMAT_ASTC_10x8_UNORM_BLOCK = 177,
+    VK_FORMAT_ASTC_10x8_SRGB_BLOCK = 178,
+    VK_FORMAT_ASTC_10x10_UNORM_BLOCK = 179,
+    VK_FORMAT_ASTC_10x10_SRGB_BLOCK = 180,
+    VK_FORMAT_ASTC_12x10_UNORM_BLOCK = 181,
+    VK_FORMAT_ASTC_12x10_SRGB_BLOCK = 182,
+    VK_FORMAT_ASTC_12x12_UNORM_BLOCK = 183,
+    VK_FORMAT_ASTC_12x12_SRGB_BLOCK = 184,
+    VK_FORMAT_BEGIN_RANGE = VK_FORMAT_UNDEFINED,
+    VK_FORMAT_END_RANGE = VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
+    VK_FORMAT_RANGE_SIZE = (VK_FORMAT_ASTC_12x12_SRGB_BLOCK - VK_FORMAT_UNDEFINED + 1),
+    VK_FORMAT_MAX_ENUM = 0x7FFFFFFF
+} VkFormat;
+
+typedef enum VkImageType {
+    VK_IMAGE_TYPE_1D = 0,
+    VK_IMAGE_TYPE_2D = 1,
+    VK_IMAGE_TYPE_3D = 2,
+    VK_IMAGE_TYPE_BEGIN_RANGE = VK_IMAGE_TYPE_1D,
+    VK_IMAGE_TYPE_END_RANGE = VK_IMAGE_TYPE_3D,
+    VK_IMAGE_TYPE_RANGE_SIZE = (VK_IMAGE_TYPE_3D - VK_IMAGE_TYPE_1D + 1),
+    VK_IMAGE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageType;
+
+typedef enum VkImageTiling {
+    VK_IMAGE_TILING_OPTIMAL = 0,
+    VK_IMAGE_TILING_LINEAR = 1,
+    VK_IMAGE_TILING_BEGIN_RANGE = VK_IMAGE_TILING_OPTIMAL,
+    VK_IMAGE_TILING_END_RANGE = VK_IMAGE_TILING_LINEAR,
+    VK_IMAGE_TILING_RANGE_SIZE = (VK_IMAGE_TILING_LINEAR - VK_IMAGE_TILING_OPTIMAL + 1),
+    VK_IMAGE_TILING_MAX_ENUM = 0x7FFFFFFF
+} VkImageTiling;
+
+typedef enum VkPhysicalDeviceType {
+    VK_PHYSICAL_DEVICE_TYPE_OTHER = 0,
+    VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU = 1,
+    VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU = 2,
+    VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU = 3,
+    VK_PHYSICAL_DEVICE_TYPE_CPU = 4,
+    VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE = VK_PHYSICAL_DEVICE_TYPE_OTHER,
+    VK_PHYSICAL_DEVICE_TYPE_END_RANGE = VK_PHYSICAL_DEVICE_TYPE_CPU,
+    VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE = (VK_PHYSICAL_DEVICE_TYPE_CPU - VK_PHYSICAL_DEVICE_TYPE_OTHER + 1),
+    VK_PHYSICAL_DEVICE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkPhysicalDeviceType;
+
+typedef enum VkQueryType {
+    VK_QUERY_TYPE_OCCLUSION = 0,
+    VK_QUERY_TYPE_PIPELINE_STATISTICS = 1,
+    VK_QUERY_TYPE_TIMESTAMP = 2,
+    VK_QUERY_TYPE_BEGIN_RANGE = VK_QUERY_TYPE_OCCLUSION,
+    VK_QUERY_TYPE_END_RANGE = VK_QUERY_TYPE_TIMESTAMP,
+    VK_QUERY_TYPE_RANGE_SIZE = (VK_QUERY_TYPE_TIMESTAMP - VK_QUERY_TYPE_OCCLUSION + 1),
+    VK_QUERY_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkQueryType;
+
+typedef enum VkSharingMode {
+    VK_SHARING_MODE_EXCLUSIVE = 0,
+    VK_SHARING_MODE_CONCURRENT = 1,
+    VK_SHARING_MODE_BEGIN_RANGE = VK_SHARING_MODE_EXCLUSIVE,
+    VK_SHARING_MODE_END_RANGE = VK_SHARING_MODE_CONCURRENT,
+    VK_SHARING_MODE_RANGE_SIZE = (VK_SHARING_MODE_CONCURRENT - VK_SHARING_MODE_EXCLUSIVE + 1),
+    VK_SHARING_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSharingMode;
+
+typedef enum VkImageLayout {
+    VK_IMAGE_LAYOUT_UNDEFINED = 0,
+    VK_IMAGE_LAYOUT_GENERAL = 1,
+    VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL = 2,
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL = 3,
+    VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL = 4,
+    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL = 5,
+    VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL = 6,
+    VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL = 7,
+    VK_IMAGE_LAYOUT_PREINITIALIZED = 8,
+    VK_IMAGE_LAYOUT_PRESENT_SRC_KHR = 1000001002,
+    VK_IMAGE_LAYOUT_BEGIN_RANGE = VK_IMAGE_LAYOUT_UNDEFINED,
+    VK_IMAGE_LAYOUT_END_RANGE = VK_IMAGE_LAYOUT_PREINITIALIZED,
+    VK_IMAGE_LAYOUT_RANGE_SIZE = (VK_IMAGE_LAYOUT_PREINITIALIZED - VK_IMAGE_LAYOUT_UNDEFINED + 1),
+    VK_IMAGE_LAYOUT_MAX_ENUM = 0x7FFFFFFF
+} VkImageLayout;
+
+typedef enum VkImageViewType {
+    VK_IMAGE_VIEW_TYPE_1D = 0,
+    VK_IMAGE_VIEW_TYPE_2D = 1,
+    VK_IMAGE_VIEW_TYPE_3D = 2,
+    VK_IMAGE_VIEW_TYPE_CUBE = 3,
+    VK_IMAGE_VIEW_TYPE_1D_ARRAY = 4,
+    VK_IMAGE_VIEW_TYPE_2D_ARRAY = 5,
+    VK_IMAGE_VIEW_TYPE_CUBE_ARRAY = 6,
+    VK_IMAGE_VIEW_TYPE_BEGIN_RANGE = VK_IMAGE_VIEW_TYPE_1D,
+    VK_IMAGE_VIEW_TYPE_END_RANGE = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,
+    VK_IMAGE_VIEW_TYPE_RANGE_SIZE = (VK_IMAGE_VIEW_TYPE_CUBE_ARRAY - VK_IMAGE_VIEW_TYPE_1D + 1),
+    VK_IMAGE_VIEW_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkImageViewType;
+
+typedef enum VkComponentSwizzle {
+    VK_COMPONENT_SWIZZLE_IDENTITY = 0,
+    VK_COMPONENT_SWIZZLE_ZERO = 1,
+    VK_COMPONENT_SWIZZLE_ONE = 2,
+    VK_COMPONENT_SWIZZLE_R = 3,
+    VK_COMPONENT_SWIZZLE_G = 4,
+    VK_COMPONENT_SWIZZLE_B = 5,
+    VK_COMPONENT_SWIZZLE_A = 6,
+    VK_COMPONENT_SWIZZLE_BEGIN_RANGE = VK_COMPONENT_SWIZZLE_IDENTITY,
+    VK_COMPONENT_SWIZZLE_END_RANGE = VK_COMPONENT_SWIZZLE_A,
+    VK_COMPONENT_SWIZZLE_RANGE_SIZE = (VK_COMPONENT_SWIZZLE_A - VK_COMPONENT_SWIZZLE_IDENTITY + 1),
+    VK_COMPONENT_SWIZZLE_MAX_ENUM = 0x7FFFFFFF
+} VkComponentSwizzle;
+
+typedef enum VkVertexInputRate {
+    VK_VERTEX_INPUT_RATE_VERTEX = 0,
+    VK_VERTEX_INPUT_RATE_INSTANCE = 1,
+    VK_VERTEX_INPUT_RATE_BEGIN_RANGE = VK_VERTEX_INPUT_RATE_VERTEX,
+    VK_VERTEX_INPUT_RATE_END_RANGE = VK_VERTEX_INPUT_RATE_INSTANCE,
+    VK_VERTEX_INPUT_RATE_RANGE_SIZE = (VK_VERTEX_INPUT_RATE_INSTANCE - VK_VERTEX_INPUT_RATE_VERTEX + 1),
+    VK_VERTEX_INPUT_RATE_MAX_ENUM = 0x7FFFFFFF
+} VkVertexInputRate;
+
+typedef enum VkPrimitiveTopology {
+    VK_PRIMITIVE_TOPOLOGY_POINT_LIST = 0,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST = 1,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP = 2,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST = 3,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP = 4,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN = 5,
+    VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY = 6,
+    VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY = 7,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY = 8,
+    VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY = 9,
+    VK_PRIMITIVE_TOPOLOGY_PATCH_LIST = 10,
+    VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE = VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
+    VK_PRIMITIVE_TOPOLOGY_END_RANGE = VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
+    VK_PRIMITIVE_TOPOLOGY_RANGE_SIZE = (VK_PRIMITIVE_TOPOLOGY_PATCH_LIST - VK_PRIMITIVE_TOPOLOGY_POINT_LIST + 1),
+    VK_PRIMITIVE_TOPOLOGY_MAX_ENUM = 0x7FFFFFFF
+} VkPrimitiveTopology;
+
+typedef enum VkPolygonMode {
+    VK_POLYGON_MODE_FILL = 0,
+    VK_POLYGON_MODE_LINE = 1,
+    VK_POLYGON_MODE_POINT = 2,
+    VK_POLYGON_MODE_BEGIN_RANGE = VK_POLYGON_MODE_FILL,
+    VK_POLYGON_MODE_END_RANGE = VK_POLYGON_MODE_POINT,
+    VK_POLYGON_MODE_RANGE_SIZE = (VK_POLYGON_MODE_POINT - VK_POLYGON_MODE_FILL + 1),
+    VK_POLYGON_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkPolygonMode;
+
+typedef enum VkFrontFace {
+    VK_FRONT_FACE_COUNTER_CLOCKWISE = 0,
+    VK_FRONT_FACE_CLOCKWISE = 1,
+    VK_FRONT_FACE_BEGIN_RANGE = VK_FRONT_FACE_COUNTER_CLOCKWISE,
+    VK_FRONT_FACE_END_RANGE = VK_FRONT_FACE_CLOCKWISE,
+    VK_FRONT_FACE_RANGE_SIZE = (VK_FRONT_FACE_CLOCKWISE - VK_FRONT_FACE_COUNTER_CLOCKWISE + 1),
+    VK_FRONT_FACE_MAX_ENUM = 0x7FFFFFFF
+} VkFrontFace;
+
+typedef enum VkCompareOp {
+    VK_COMPARE_OP_NEVER = 0,
+    VK_COMPARE_OP_LESS = 1,
+    VK_COMPARE_OP_EQUAL = 2,
+    VK_COMPARE_OP_LESS_OR_EQUAL = 3,
+    VK_COMPARE_OP_GREATER = 4,
+    VK_COMPARE_OP_NOT_EQUAL = 5,
+    VK_COMPARE_OP_GREATER_OR_EQUAL = 6,
+    VK_COMPARE_OP_ALWAYS = 7,
+    VK_COMPARE_OP_BEGIN_RANGE = VK_COMPARE_OP_NEVER,
+    VK_COMPARE_OP_END_RANGE = VK_COMPARE_OP_ALWAYS,
+    VK_COMPARE_OP_RANGE_SIZE = (VK_COMPARE_OP_ALWAYS - VK_COMPARE_OP_NEVER + 1),
+    VK_COMPARE_OP_MAX_ENUM = 0x7FFFFFFF
+} VkCompareOp;
+
+typedef enum VkStencilOp {
+    VK_STENCIL_OP_KEEP = 0,
+    VK_STENCIL_OP_ZERO = 1,
+    VK_STENCIL_OP_REPLACE = 2,
+    VK_STENCIL_OP_INCREMENT_AND_CLAMP = 3,
+    VK_STENCIL_OP_DECREMENT_AND_CLAMP = 4,
+    VK_STENCIL_OP_INVERT = 5,
+    VK_STENCIL_OP_INCREMENT_AND_WRAP = 6,
+    VK_STENCIL_OP_DECREMENT_AND_WRAP = 7,
+    VK_STENCIL_OP_BEGIN_RANGE = VK_STENCIL_OP_KEEP,
+    VK_STENCIL_OP_END_RANGE = VK_STENCIL_OP_DECREMENT_AND_WRAP,
+    VK_STENCIL_OP_RANGE_SIZE = (VK_STENCIL_OP_DECREMENT_AND_WRAP - VK_STENCIL_OP_KEEP + 1),
+    VK_STENCIL_OP_MAX_ENUM = 0x7FFFFFFF
+} VkStencilOp;
+
+typedef enum VkLogicOp {
+    VK_LOGIC_OP_CLEAR = 0,
+    VK_LOGIC_OP_AND = 1,
+    VK_LOGIC_OP_AND_REVERSE = 2,
+    VK_LOGIC_OP_COPY = 3,
+    VK_LOGIC_OP_AND_INVERTED = 4,
+    VK_LOGIC_OP_NO_OP = 5,
+    VK_LOGIC_OP_XOR = 6,
+    VK_LOGIC_OP_OR = 7,
+    VK_LOGIC_OP_NOR = 8,
+    VK_LOGIC_OP_EQUIVALENT = 9,
+    VK_LOGIC_OP_INVERT = 10,
+    VK_LOGIC_OP_OR_REVERSE = 11,
+    VK_LOGIC_OP_COPY_INVERTED = 12,
+    VK_LOGIC_OP_OR_INVERTED = 13,
+    VK_LOGIC_OP_NAND = 14,
+    VK_LOGIC_OP_SET = 15,
+    VK_LOGIC_OP_BEGIN_RANGE = VK_LOGIC_OP_CLEAR,
+    VK_LOGIC_OP_END_RANGE = VK_LOGIC_OP_SET,
+    VK_LOGIC_OP_RANGE_SIZE = (VK_LOGIC_OP_SET - VK_LOGIC_OP_CLEAR + 1),
+    VK_LOGIC_OP_MAX_ENUM = 0x7FFFFFFF
+} VkLogicOp;
+
+typedef enum VkBlendFactor {
+    VK_BLEND_FACTOR_ZERO = 0,
+    VK_BLEND_FACTOR_ONE = 1,
+    VK_BLEND_FACTOR_SRC_COLOR = 2,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = 3,
+    VK_BLEND_FACTOR_DST_COLOR = 4,
+    VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR = 5,
+    VK_BLEND_FACTOR_SRC_ALPHA = 6,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = 7,
+    VK_BLEND_FACTOR_DST_ALPHA = 8,
+    VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = 9,
+    VK_BLEND_FACTOR_CONSTANT_COLOR = 10,
+    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR = 11,
+    VK_BLEND_FACTOR_CONSTANT_ALPHA = 12,
+    VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA = 13,
+    VK_BLEND_FACTOR_SRC_ALPHA_SATURATE = 14,
+    VK_BLEND_FACTOR_SRC1_COLOR = 15,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR = 16,
+    VK_BLEND_FACTOR_SRC1_ALPHA = 17,
+    VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA = 18,
+    VK_BLEND_FACTOR_BEGIN_RANGE = VK_BLEND_FACTOR_ZERO,
+    VK_BLEND_FACTOR_END_RANGE = VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
+    VK_BLEND_FACTOR_RANGE_SIZE = (VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA - VK_BLEND_FACTOR_ZERO + 1),
+    VK_BLEND_FACTOR_MAX_ENUM = 0x7FFFFFFF
+} VkBlendFactor;
+
+typedef enum VkBlendOp {
+    VK_BLEND_OP_ADD = 0,
+    VK_BLEND_OP_SUBTRACT = 1,
+    VK_BLEND_OP_REVERSE_SUBTRACT = 2,
+    VK_BLEND_OP_MIN = 3,
+    VK_BLEND_OP_MAX = 4,
+    VK_BLEND_OP_BEGIN_RANGE = VK_BLEND_OP_ADD,
+    VK_BLEND_OP_END_RANGE = VK_BLEND_OP_MAX,
+    VK_BLEND_OP_RANGE_SIZE = (VK_BLEND_OP_MAX - VK_BLEND_OP_ADD + 1),
+    VK_BLEND_OP_MAX_ENUM = 0x7FFFFFFF
+} VkBlendOp;
+
+typedef enum VkDynamicState {
+    VK_DYNAMIC_STATE_VIEWPORT = 0,
+    VK_DYNAMIC_STATE_SCISSOR = 1,
+    VK_DYNAMIC_STATE_LINE_WIDTH = 2,
+    VK_DYNAMIC_STATE_DEPTH_BIAS = 3,
+    VK_DYNAMIC_STATE_BLEND_CONSTANTS = 4,
+    VK_DYNAMIC_STATE_DEPTH_BOUNDS = 5,
+    VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK = 6,
+    VK_DYNAMIC_STATE_STENCIL_WRITE_MASK = 7,
+    VK_DYNAMIC_STATE_STENCIL_REFERENCE = 8,
+    VK_DYNAMIC_STATE_BEGIN_RANGE = VK_DYNAMIC_STATE_VIEWPORT,
+    VK_DYNAMIC_STATE_END_RANGE = VK_DYNAMIC_STATE_STENCIL_REFERENCE,
+    VK_DYNAMIC_STATE_RANGE_SIZE = (VK_DYNAMIC_STATE_STENCIL_REFERENCE - VK_DYNAMIC_STATE_VIEWPORT + 1),
+    VK_DYNAMIC_STATE_MAX_ENUM = 0x7FFFFFFF
+} VkDynamicState;
+
+typedef enum VkFilter {
+    VK_FILTER_NEAREST = 0,
+    VK_FILTER_LINEAR = 1,
+    VK_FILTER_BEGIN_RANGE = VK_FILTER_NEAREST,
+    VK_FILTER_END_RANGE = VK_FILTER_LINEAR,
+    VK_FILTER_RANGE_SIZE = (VK_FILTER_LINEAR - VK_FILTER_NEAREST + 1),
+    VK_FILTER_MAX_ENUM = 0x7FFFFFFF
+} VkFilter;
+
+typedef enum VkSamplerMipmapMode {
+    VK_SAMPLER_MIPMAP_MODE_NEAREST = 0,
+    VK_SAMPLER_MIPMAP_MODE_LINEAR = 1,
+    VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE = VK_SAMPLER_MIPMAP_MODE_NEAREST,
+    VK_SAMPLER_MIPMAP_MODE_END_RANGE = VK_SAMPLER_MIPMAP_MODE_LINEAR,
+    VK_SAMPLER_MIPMAP_MODE_RANGE_SIZE = (VK_SAMPLER_MIPMAP_MODE_LINEAR - VK_SAMPLER_MIPMAP_MODE_NEAREST + 1),
+    VK_SAMPLER_MIPMAP_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerMipmapMode;
+
+typedef enum VkSamplerAddressMode {
+    VK_SAMPLER_ADDRESS_MODE_REPEAT = 0,
+    VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT = 1,
+    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE = 2,
+    VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER = 3,
+    VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE = 4,
+    VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE = VK_SAMPLER_ADDRESS_MODE_REPEAT,
+    VK_SAMPLER_ADDRESS_MODE_END_RANGE = VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
+    VK_SAMPLER_ADDRESS_MODE_RANGE_SIZE = (VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE - VK_SAMPLER_ADDRESS_MODE_REPEAT + 1),
+    VK_SAMPLER_ADDRESS_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkSamplerAddressMode;
+
+typedef enum VkBorderColor {
+    VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK = 0,
+    VK_BORDER_COLOR_INT_TRANSPARENT_BLACK = 1,
+    VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK = 2,
+    VK_BORDER_COLOR_INT_OPAQUE_BLACK = 3,
+    VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE = 4,
+    VK_BORDER_COLOR_INT_OPAQUE_WHITE = 5,
+    VK_BORDER_COLOR_BEGIN_RANGE = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,
+    VK_BORDER_COLOR_END_RANGE = VK_BORDER_COLOR_INT_OPAQUE_WHITE,
+    VK_BORDER_COLOR_RANGE_SIZE = (VK_BORDER_COLOR_INT_OPAQUE_WHITE - VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK + 1),
+    VK_BORDER_COLOR_MAX_ENUM = 0x7FFFFFFF
+} VkBorderColor;
+
+typedef enum VkDescriptorType {
+    VK_DESCRIPTOR_TYPE_SAMPLER = 0,
+    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER = 1,
+    VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE = 2,
+    VK_DESCRIPTOR_TYPE_STORAGE_IMAGE = 3,
+    VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER = 4,
+    VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER = 5,
+    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER = 6,
+    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER = 7,
+    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
+    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC = 9,
+    VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT = 10,
+    VK_DESCRIPTOR_TYPE_BEGIN_RANGE = VK_DESCRIPTOR_TYPE_SAMPLER,
+    VK_DESCRIPTOR_TYPE_END_RANGE = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+    VK_DESCRIPTOR_TYPE_RANGE_SIZE = (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT - VK_DESCRIPTOR_TYPE_SAMPLER + 1),
+    VK_DESCRIPTOR_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDescriptorType;
+
+typedef enum VkAttachmentLoadOp {
+    VK_ATTACHMENT_LOAD_OP_LOAD = 0,
+    VK_ATTACHMENT_LOAD_OP_CLEAR = 1,
+    VK_ATTACHMENT_LOAD_OP_DONT_CARE = 2,
+    VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE = VK_ATTACHMENT_LOAD_OP_LOAD,
+    VK_ATTACHMENT_LOAD_OP_END_RANGE = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+    VK_ATTACHMENT_LOAD_OP_RANGE_SIZE = (VK_ATTACHMENT_LOAD_OP_DONT_CARE - VK_ATTACHMENT_LOAD_OP_LOAD + 1),
+    VK_ATTACHMENT_LOAD_OP_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentLoadOp;
+
+typedef enum VkAttachmentStoreOp {
+    VK_ATTACHMENT_STORE_OP_STORE = 0,
+    VK_ATTACHMENT_STORE_OP_DONT_CARE = 1,
+    VK_ATTACHMENT_STORE_OP_BEGIN_RANGE = VK_ATTACHMENT_STORE_OP_STORE,
+    VK_ATTACHMENT_STORE_OP_END_RANGE = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+    VK_ATTACHMENT_STORE_OP_RANGE_SIZE = (VK_ATTACHMENT_STORE_OP_DONT_CARE - VK_ATTACHMENT_STORE_OP_STORE + 1),
+    VK_ATTACHMENT_STORE_OP_MAX_ENUM = 0x7FFFFFFF
+} VkAttachmentStoreOp;
+
+typedef enum VkPipelineBindPoint {
+    VK_PIPELINE_BIND_POINT_GRAPHICS = 0,
+    VK_PIPELINE_BIND_POINT_COMPUTE = 1,
+    VK_PIPELINE_BIND_POINT_BEGIN_RANGE = VK_PIPELINE_BIND_POINT_GRAPHICS,
+    VK_PIPELINE_BIND_POINT_END_RANGE = VK_PIPELINE_BIND_POINT_COMPUTE,
+    VK_PIPELINE_BIND_POINT_RANGE_SIZE = (VK_PIPELINE_BIND_POINT_COMPUTE - VK_PIPELINE_BIND_POINT_GRAPHICS + 1),
+    VK_PIPELINE_BIND_POINT_MAX_ENUM = 0x7FFFFFFF
+} VkPipelineBindPoint;
+
+typedef enum VkCommandBufferLevel {
+    VK_COMMAND_BUFFER_LEVEL_PRIMARY = 0,
+    VK_COMMAND_BUFFER_LEVEL_SECONDARY = 1,
+    VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+    VK_COMMAND_BUFFER_LEVEL_END_RANGE = VK_COMMAND_BUFFER_LEVEL_SECONDARY,
+    VK_COMMAND_BUFFER_LEVEL_RANGE_SIZE = (VK_COMMAND_BUFFER_LEVEL_SECONDARY - VK_COMMAND_BUFFER_LEVEL_PRIMARY + 1),
+    VK_COMMAND_BUFFER_LEVEL_MAX_ENUM = 0x7FFFFFFF
+} VkCommandBufferLevel;
+
+typedef enum VkIndexType {
+    VK_INDEX_TYPE_UINT16 = 0,
+    VK_INDEX_TYPE_UINT32 = 1,
+    VK_INDEX_TYPE_BEGIN_RANGE = VK_INDEX_TYPE_UINT16,
+    VK_INDEX_TYPE_END_RANGE = VK_INDEX_TYPE_UINT32,
+    VK_INDEX_TYPE_RANGE_SIZE = (VK_INDEX_TYPE_UINT32 - VK_INDEX_TYPE_UINT16 + 1),
+    VK_INDEX_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkIndexType;
+
+typedef enum VkSubpassContents {
+    VK_SUBPASS_CONTENTS_INLINE = 0,
+    VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS = 1,
+    VK_SUBPASS_CONTENTS_BEGIN_RANGE = VK_SUBPASS_CONTENTS_INLINE,
+    VK_SUBPASS_CONTENTS_END_RANGE = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS,
+    VK_SUBPASS_CONTENTS_RANGE_SIZE = (VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS - VK_SUBPASS_CONTENTS_INLINE + 1),
+    VK_SUBPASS_CONTENTS_MAX_ENUM = 0x7FFFFFFF
+} VkSubpassContents;
+
+typedef VkFlags VkInstanceCreateFlags;
+
+typedef enum VkFormatFeatureFlagBits {
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT = 0x00000001,
+    VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT = 0x00000002,
+    VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT = 0x00000004,
+    VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000008,
+    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT = 0x00000010,
+    VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT = 0x00000020,
+    VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT = 0x00000040,
+    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT = 0x00000080,
+    VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT = 0x00000100,
+    VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000200,
+    VK_FORMAT_FEATURE_BLIT_SRC_BIT = 0x00000400,
+    VK_FORMAT_FEATURE_BLIT_DST_BIT = 0x00000800,
+    VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT = 0x00001000,
+} VkFormatFeatureFlagBits;
+typedef VkFlags VkFormatFeatureFlags;
+
+typedef enum VkImageUsageFlagBits {
+    VK_IMAGE_USAGE_TRANSFER_SRC_BIT = 0x00000001,
+    VK_IMAGE_USAGE_TRANSFER_DST_BIT = 0x00000002,
+    VK_IMAGE_USAGE_SAMPLED_BIT = 0x00000004,
+    VK_IMAGE_USAGE_STORAGE_BIT = 0x00000008,
+    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT = 0x00000010,
+    VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = 0x00000020,
+    VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT = 0x00000040,
+    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT = 0x00000080,
+} VkImageUsageFlagBits;
+typedef VkFlags VkImageUsageFlags;
+
+typedef enum VkImageCreateFlagBits {
+    VK_IMAGE_CREATE_SPARSE_BINDING_BIT = 0x00000001,
+    VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+    VK_IMAGE_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+    VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT = 0x00000008,
+    VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT = 0x00000010,
+} VkImageCreateFlagBits;
+typedef VkFlags VkImageCreateFlags;
+
+typedef enum VkSampleCountFlagBits {
+    VK_SAMPLE_COUNT_1_BIT = 0x00000001,
+    VK_SAMPLE_COUNT_2_BIT = 0x00000002,
+    VK_SAMPLE_COUNT_4_BIT = 0x00000004,
+    VK_SAMPLE_COUNT_8_BIT = 0x00000008,
+    VK_SAMPLE_COUNT_16_BIT = 0x00000010,
+    VK_SAMPLE_COUNT_32_BIT = 0x00000020,
+    VK_SAMPLE_COUNT_64_BIT = 0x00000040,
+} VkSampleCountFlagBits;
+typedef VkFlags VkSampleCountFlags;
+
+typedef enum VkQueueFlagBits {
+    VK_QUEUE_GRAPHICS_BIT = 0x00000001,
+    VK_QUEUE_COMPUTE_BIT = 0x00000002,
+    VK_QUEUE_TRANSFER_BIT = 0x00000004,
+    VK_QUEUE_SPARSE_BINDING_BIT = 0x00000008,
+} VkQueueFlagBits;
+typedef VkFlags VkQueueFlags;
+
+typedef enum VkMemoryPropertyFlagBits {
+    VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT = 0x00000001,
+    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT = 0x00000002,
+    VK_MEMORY_PROPERTY_HOST_COHERENT_BIT = 0x00000004,
+    VK_MEMORY_PROPERTY_HOST_CACHED_BIT = 0x00000008,
+    VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT = 0x00000010,
+} VkMemoryPropertyFlagBits;
+typedef VkFlags VkMemoryPropertyFlags;
+
+typedef enum VkMemoryHeapFlagBits {
+    VK_MEMORY_HEAP_DEVICE_LOCAL_BIT = 0x00000001,
+} VkMemoryHeapFlagBits;
+typedef VkFlags VkMemoryHeapFlags;
+typedef VkFlags VkDeviceCreateFlags;
+typedef VkFlags VkDeviceQueueCreateFlags;
+
+typedef enum VkPipelineStageFlagBits {
+    VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT = 0x00000001,
+    VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT = 0x00000002,
+    VK_PIPELINE_STAGE_VERTEX_INPUT_BIT = 0x00000004,
+    VK_PIPELINE_STAGE_VERTEX_SHADER_BIT = 0x00000008,
+    VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT = 0x00000010,
+    VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT = 0x00000020,
+    VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT = 0x00000040,
+    VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT = 0x00000080,
+    VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT = 0x00000100,
+    VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT = 0x00000200,
+    VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT = 0x00000400,
+    VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT = 0x00000800,
+    VK_PIPELINE_STAGE_TRANSFER_BIT = 0x00001000,
+    VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT = 0x00002000,
+    VK_PIPELINE_STAGE_HOST_BIT = 0x00004000,
+    VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT = 0x00008000,
+    VK_PIPELINE_STAGE_ALL_COMMANDS_BIT = 0x00010000,
+} VkPipelineStageFlagBits;
+typedef VkFlags VkPipelineStageFlags;
+typedef VkFlags VkMemoryMapFlags;
+
+typedef enum VkImageAspectFlagBits {
+    VK_IMAGE_ASPECT_COLOR_BIT = 0x00000001,
+    VK_IMAGE_ASPECT_DEPTH_BIT = 0x00000002,
+    VK_IMAGE_ASPECT_STENCIL_BIT = 0x00000004,
+    VK_IMAGE_ASPECT_METADATA_BIT = 0x00000008,
+} VkImageAspectFlagBits;
+typedef VkFlags VkImageAspectFlags;
+
+typedef enum VkSparseImageFormatFlagBits {
+    VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT = 0x00000001,
+    VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT = 0x00000002,
+    VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT = 0x00000004,
+} VkSparseImageFormatFlagBits;
+typedef VkFlags VkSparseImageFormatFlags;
+
+typedef enum VkSparseMemoryBindFlagBits {
+    VK_SPARSE_MEMORY_BIND_METADATA_BIT = 0x00000001,
+} VkSparseMemoryBindFlagBits;
+typedef VkFlags VkSparseMemoryBindFlags;
+
+typedef enum VkFenceCreateFlagBits {
+    VK_FENCE_CREATE_SIGNALED_BIT = 0x00000001,
+} VkFenceCreateFlagBits;
+typedef VkFlags VkFenceCreateFlags;
+typedef VkFlags VkSemaphoreCreateFlags;
+typedef VkFlags VkEventCreateFlags;
+typedef VkFlags VkQueryPoolCreateFlags;
+
+typedef enum VkQueryPipelineStatisticFlagBits {
+    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT = 0x00000001,
+    VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT = 0x00000002,
+    VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT = 0x00000004,
+    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT = 0x00000008,
+    VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT = 0x00000010,
+    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT = 0x00000020,
+    VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT = 0x00000040,
+    VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT = 0x00000080,
+    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT = 0x00000100,
+    VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT = 0x00000200,
+    VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT = 0x00000400,
+} VkQueryPipelineStatisticFlagBits;
+typedef VkFlags VkQueryPipelineStatisticFlags;
+
+typedef enum VkQueryResultFlagBits {
+    VK_QUERY_RESULT_64_BIT = 0x00000001,
+    VK_QUERY_RESULT_WAIT_BIT = 0x00000002,
+    VK_QUERY_RESULT_WITH_AVAILABILITY_BIT = 0x00000004,
+    VK_QUERY_RESULT_PARTIAL_BIT = 0x00000008,
+} VkQueryResultFlagBits;
+typedef VkFlags VkQueryResultFlags;
+
+typedef enum VkBufferCreateFlagBits {
+    VK_BUFFER_CREATE_SPARSE_BINDING_BIT = 0x00000001,
+    VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT = 0x00000002,
+    VK_BUFFER_CREATE_SPARSE_ALIASED_BIT = 0x00000004,
+} VkBufferCreateFlagBits;
+typedef VkFlags VkBufferCreateFlags;
+
+typedef enum VkBufferUsageFlagBits {
+    VK_BUFFER_USAGE_TRANSFER_SRC_BIT = 0x00000001,
+    VK_BUFFER_USAGE_TRANSFER_DST_BIT = 0x00000002,
+    VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT = 0x00000004,
+    VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT = 0x00000008,
+    VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT = 0x00000010,
+    VK_BUFFER_USAGE_STORAGE_BUFFER_BIT = 0x00000020,
+    VK_BUFFER_USAGE_INDEX_BUFFER_BIT = 0x00000040,
+    VK_BUFFER_USAGE_VERTEX_BUFFER_BIT = 0x00000080,
+    VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT = 0x00000100,
+} VkBufferUsageFlagBits;
+typedef VkFlags VkBufferUsageFlags;
+typedef VkFlags VkBufferViewCreateFlags;
+typedef VkFlags VkImageViewCreateFlags;
+typedef VkFlags VkShaderModuleCreateFlags;
+typedef VkFlags VkPipelineCacheCreateFlags;
+
+typedef enum VkPipelineCreateFlagBits {
+    VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT = 0x00000001,
+    VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT = 0x00000002,
+    VK_PIPELINE_CREATE_DERIVATIVE_BIT = 0x00000004,
+} VkPipelineCreateFlagBits;
+typedef VkFlags VkPipelineCreateFlags;
+typedef VkFlags VkPipelineShaderStageCreateFlags;
+
+typedef enum VkShaderStageFlagBits {
+    VK_SHADER_STAGE_VERTEX_BIT = 0x00000001,
+    VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT = 0x00000002,
+    VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT = 0x00000004,
+    VK_SHADER_STAGE_GEOMETRY_BIT = 0x00000008,
+    VK_SHADER_STAGE_FRAGMENT_BIT = 0x00000010,
+    VK_SHADER_STAGE_COMPUTE_BIT = 0x00000020,
+    VK_SHADER_STAGE_ALL_GRAPHICS = 0x1F,
+    VK_SHADER_STAGE_ALL = 0x7FFFFFFF,
+} VkShaderStageFlagBits;
+typedef VkFlags VkPipelineVertexInputStateCreateFlags;
+typedef VkFlags VkPipelineInputAssemblyStateCreateFlags;
+typedef VkFlags VkPipelineTessellationStateCreateFlags;
+typedef VkFlags VkPipelineViewportStateCreateFlags;
+typedef VkFlags VkPipelineRasterizationStateCreateFlags;
+
+typedef enum VkCullModeFlagBits {
+    VK_CULL_MODE_NONE = 0,
+    VK_CULL_MODE_FRONT_BIT = 0x00000001,
+    VK_CULL_MODE_BACK_BIT = 0x00000002,
+    VK_CULL_MODE_FRONT_AND_BACK = 0x3,
+} VkCullModeFlagBits;
+typedef VkFlags VkCullModeFlags;
+typedef VkFlags VkPipelineMultisampleStateCreateFlags;
+typedef VkFlags VkPipelineDepthStencilStateCreateFlags;
+typedef VkFlags VkPipelineColorBlendStateCreateFlags;
+
+typedef enum VkColorComponentFlagBits {
+    VK_COLOR_COMPONENT_R_BIT = 0x00000001,
+    VK_COLOR_COMPONENT_G_BIT = 0x00000002,
+    VK_COLOR_COMPONENT_B_BIT = 0x00000004,
+    VK_COLOR_COMPONENT_A_BIT = 0x00000008,
+} VkColorComponentFlagBits;
+typedef VkFlags VkColorComponentFlags;
+typedef VkFlags VkPipelineDynamicStateCreateFlags;
+typedef VkFlags VkPipelineLayoutCreateFlags;
+typedef VkFlags VkShaderStageFlags;
+typedef VkFlags VkSamplerCreateFlags;
+typedef VkFlags VkDescriptorSetLayoutCreateFlags;
+
+typedef enum VkDescriptorPoolCreateFlagBits {
+    VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT = 0x00000001,
+} VkDescriptorPoolCreateFlagBits;
+typedef VkFlags VkDescriptorPoolCreateFlags;
+typedef VkFlags VkDescriptorPoolResetFlags;
+typedef VkFlags VkFramebufferCreateFlags;
+typedef VkFlags VkRenderPassCreateFlags;
+
+typedef enum VkAttachmentDescriptionFlagBits {
+    VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT = 0x00000001,
+} VkAttachmentDescriptionFlagBits;
+typedef VkFlags VkAttachmentDescriptionFlags;
+typedef VkFlags VkSubpassDescriptionFlags;
+
+typedef enum VkAccessFlagBits {
+    VK_ACCESS_INDIRECT_COMMAND_READ_BIT = 0x00000001,
+    VK_ACCESS_INDEX_READ_BIT = 0x00000002,
+    VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT = 0x00000004,
+    VK_ACCESS_UNIFORM_READ_BIT = 0x00000008,
+    VK_ACCESS_INPUT_ATTACHMENT_READ_BIT = 0x00000010,
+    VK_ACCESS_SHADER_READ_BIT = 0x00000020,
+    VK_ACCESS_SHADER_WRITE_BIT = 0x00000040,
+    VK_ACCESS_COLOR_ATTACHMENT_READ_BIT = 0x00000080,
+    VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT = 0x00000100,
+    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT = 0x00000200,
+    VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT = 0x00000400,
+    VK_ACCESS_TRANSFER_READ_BIT = 0x00000800,
+    VK_ACCESS_TRANSFER_WRITE_BIT = 0x00001000,
+    VK_ACCESS_HOST_READ_BIT = 0x00002000,
+    VK_ACCESS_HOST_WRITE_BIT = 0x00004000,
+    VK_ACCESS_MEMORY_READ_BIT = 0x00008000,
+    VK_ACCESS_MEMORY_WRITE_BIT = 0x00010000,
+} VkAccessFlagBits;
+typedef VkFlags VkAccessFlags;
+
+typedef enum VkDependencyFlagBits {
+    VK_DEPENDENCY_BY_REGION_BIT = 0x00000001,
+} VkDependencyFlagBits;
+typedef VkFlags VkDependencyFlags;
+
+typedef enum VkCommandPoolCreateFlagBits {
+    VK_COMMAND_POOL_CREATE_TRANSIENT_BIT = 0x00000001,
+    VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT = 0x00000002,
+} VkCommandPoolCreateFlagBits;
+typedef VkFlags VkCommandPoolCreateFlags;
+
+typedef enum VkCommandPoolResetFlagBits {
+    VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
+} VkCommandPoolResetFlagBits;
+typedef VkFlags VkCommandPoolResetFlags;
+
+typedef enum VkCommandBufferUsageFlagBits {
+    VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT = 0x00000001,
+    VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT = 0x00000002,
+    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT = 0x00000004,
+} VkCommandBufferUsageFlagBits;
+typedef VkFlags VkCommandBufferUsageFlags;
+
+typedef enum VkQueryControlFlagBits {
+    VK_QUERY_CONTROL_PRECISE_BIT = 0x00000001,
+} VkQueryControlFlagBits;
+typedef VkFlags VkQueryControlFlags;
+
+typedef enum VkCommandBufferResetFlagBits {
+    VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT = 0x00000001,
+} VkCommandBufferResetFlagBits;
+typedef VkFlags VkCommandBufferResetFlags;
+
+typedef enum VkStencilFaceFlagBits {
+    VK_STENCIL_FACE_FRONT_BIT = 0x00000001,
+    VK_STENCIL_FACE_BACK_BIT = 0x00000002,
+    VK_STENCIL_FRONT_AND_BACK = 0x3,
+} VkStencilFaceFlagBits;
+typedef VkFlags VkStencilFaceFlags;
+
+typedef void* (VKAPI_PTR *PFN_vkAllocationFunction)(
+    void*                                       pUserData,
+    size_t                                      size,
+    size_t                                      alignment,
+    VkSystemAllocationScope                     allocationScope);
+
+typedef void* (VKAPI_PTR *PFN_vkReallocationFunction)(
+    void*                                       pUserData,
+    void*                                       pOriginal,
+    size_t                                      size,
+    size_t                                      alignment,
+    VkSystemAllocationScope                     allocationScope);
+
+typedef void (VKAPI_PTR *PFN_vkFreeFunction)(
+    void*                                       pUserData,
+    void*                                       pMemory);
+
+typedef void (VKAPI_PTR *PFN_vkInternalAllocationNotification)(
+    void*                                       pUserData,
+    size_t                                      size,
+    VkInternalAllocationType                    allocationType,
+    VkSystemAllocationScope                     allocationScope);
+
+typedef void (VKAPI_PTR *PFN_vkInternalFreeNotification)(
+    void*                                       pUserData,
+    size_t                                      size,
+    VkInternalAllocationType                    allocationType,
+    VkSystemAllocationScope                     allocationScope);
+
+typedef void (VKAPI_PTR *PFN_vkVoidFunction)(void);
+
+typedef struct VkApplicationInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    const char*        pApplicationName;
+    uint32_t           applicationVersion;
+    const char*        pEngineName;
+    uint32_t           engineVersion;
+    uint32_t           apiVersion;
+} VkApplicationInfo;
+
+typedef struct VkInstanceCreateInfo {
+    VkStructureType             sType;
+    const void*                 pNext;
+    VkInstanceCreateFlags       flags;
+    const VkApplicationInfo*    pApplicationInfo;
+    uint32_t                    enabledLayerCount;
+    const char* const*          ppEnabledLayerNames;
+    uint32_t                    enabledExtensionCount;
+    const char* const*          ppEnabledExtensionNames;
+} VkInstanceCreateInfo;
+
+typedef struct VkAllocationCallbacks {
+    void*                                   pUserData;
+    PFN_vkAllocationFunction                pfnAllocation;
+    PFN_vkReallocationFunction              pfnReallocation;
+    PFN_vkFreeFunction                      pfnFree;
+    PFN_vkInternalAllocationNotification    pfnInternalAllocation;
+    PFN_vkInternalFreeNotification          pfnInternalFree;
+} VkAllocationCallbacks;
+
+typedef struct VkPhysicalDeviceFeatures {
+    VkBool32    robustBufferAccess;
+    VkBool32    fullDrawIndexUint32;
+    VkBool32    imageCubeArray;
+    VkBool32    independentBlend;
+    VkBool32    geometryShader;
+    VkBool32    tessellationShader;
+    VkBool32    sampleRateShading;
+    VkBool32    dualSrcBlend;
+    VkBool32    logicOp;
+    VkBool32    multiDrawIndirect;
+    VkBool32    drawIndirectFirstInstance;
+    VkBool32    depthClamp;
+    VkBool32    depthBiasClamp;
+    VkBool32    fillModeNonSolid;
+    VkBool32    depthBounds;
+    VkBool32    wideLines;
+    VkBool32    largePoints;
+    VkBool32    alphaToOne;
+    VkBool32    multiViewport;
+    VkBool32    samplerAnisotropy;
+    VkBool32    textureCompressionETC2;
+    VkBool32    textureCompressionASTC_LDR;
+    VkBool32    textureCompressionBC;
+    VkBool32    occlusionQueryPrecise;
+    VkBool32    pipelineStatisticsQuery;
+    VkBool32    vertexPipelineStoresAndAtomics;
+    VkBool32    fragmentStoresAndAtomics;
+    VkBool32    shaderTessellationAndGeometryPointSize;
+    VkBool32    shaderImageGatherExtended;
+    VkBool32    shaderStorageImageExtendedFormats;
+    VkBool32    shaderStorageImageMultisample;
+    VkBool32    shaderStorageImageReadWithoutFormat;
+    VkBool32    shaderStorageImageWriteWithoutFormat;
+    VkBool32    shaderUniformBufferArrayDynamicIndexing;
+    VkBool32    shaderSampledImageArrayDynamicIndexing;
+    VkBool32    shaderStorageBufferArrayDynamicIndexing;
+    VkBool32    shaderStorageImageArrayDynamicIndexing;
+    VkBool32    shaderClipDistance;
+    VkBool32    shaderCullDistance;
+    VkBool32    shaderFloat64;
+    VkBool32    shaderInt64;
+    VkBool32    shaderInt16;
+    VkBool32    shaderResourceResidency;
+    VkBool32    shaderResourceMinLod;
+    VkBool32    sparseBinding;
+    VkBool32    sparseResidencyBuffer;
+    VkBool32    sparseResidencyImage2D;
+    VkBool32    sparseResidencyImage3D;
+    VkBool32    sparseResidency2Samples;
+    VkBool32    sparseResidency4Samples;
+    VkBool32    sparseResidency8Samples;
+    VkBool32    sparseResidency16Samples;
+    VkBool32    sparseResidencyAliased;
+    VkBool32    variableMultisampleRate;
+    VkBool32    inheritedQueries;
+} VkPhysicalDeviceFeatures;
+
+typedef struct VkFormatProperties {
+    VkFormatFeatureFlags    linearTilingFeatures;
+    VkFormatFeatureFlags    optimalTilingFeatures;
+    VkFormatFeatureFlags    bufferFeatures;
+} VkFormatProperties;
+
+typedef struct VkExtent3D {
+    uint32_t    width;
+    uint32_t    height;
+    uint32_t    depth;
+} VkExtent3D;
+
+typedef struct VkImageFormatProperties {
+    VkExtent3D            maxExtent;
+    uint32_t              maxMipLevels;
+    uint32_t              maxArrayLayers;
+    VkSampleCountFlags    sampleCounts;
+    VkDeviceSize          maxResourceSize;
+} VkImageFormatProperties;
+
+typedef struct VkPhysicalDeviceLimits {
+    uint32_t              maxImageDimension1D;
+    uint32_t              maxImageDimension2D;
+    uint32_t              maxImageDimension3D;
+    uint32_t              maxImageDimensionCube;
+    uint32_t              maxImageArrayLayers;
+    uint32_t              maxTexelBufferElements;
+    uint32_t              maxUniformBufferRange;
+    uint32_t              maxStorageBufferRange;
+    uint32_t              maxPushConstantsSize;
+    uint32_t              maxMemoryAllocationCount;
+    uint32_t              maxSamplerAllocationCount;
+    VkDeviceSize          bufferImageGranularity;
+    VkDeviceSize          sparseAddressSpaceSize;
+    uint32_t              maxBoundDescriptorSets;
+    uint32_t              maxPerStageDescriptorSamplers;
+    uint32_t              maxPerStageDescriptorUniformBuffers;
+    uint32_t              maxPerStageDescriptorStorageBuffers;
+    uint32_t              maxPerStageDescriptorSampledImages;
+    uint32_t              maxPerStageDescriptorStorageImages;
+    uint32_t              maxPerStageDescriptorInputAttachments;
+    uint32_t              maxPerStageResources;
+    uint32_t              maxDescriptorSetSamplers;
+    uint32_t              maxDescriptorSetUniformBuffers;
+    uint32_t              maxDescriptorSetUniformBuffersDynamic;
+    uint32_t              maxDescriptorSetStorageBuffers;
+    uint32_t              maxDescriptorSetStorageBuffersDynamic;
+    uint32_t              maxDescriptorSetSampledImages;
+    uint32_t              maxDescriptorSetStorageImages;
+    uint32_t              maxDescriptorSetInputAttachments;
+    uint32_t              maxVertexInputAttributes;
+    uint32_t              maxVertexInputBindings;
+    uint32_t              maxVertexInputAttributeOffset;
+    uint32_t              maxVertexInputBindingStride;
+    uint32_t              maxVertexOutputComponents;
+    uint32_t              maxTessellationGenerationLevel;
+    uint32_t              maxTessellationPatchSize;
+    uint32_t              maxTessellationControlPerVertexInputComponents;
+    uint32_t              maxTessellationControlPerVertexOutputComponents;
+    uint32_t              maxTessellationControlPerPatchOutputComponents;
+    uint32_t              maxTessellationControlTotalOutputComponents;
+    uint32_t              maxTessellationEvaluationInputComponents;
+    uint32_t              maxTessellationEvaluationOutputComponents;
+    uint32_t              maxGeometryShaderInvocations;
+    uint32_t              maxGeometryInputComponents;
+    uint32_t              maxGeometryOutputComponents;
+    uint32_t              maxGeometryOutputVertices;
+    uint32_t              maxGeometryTotalOutputComponents;
+    uint32_t              maxFragmentInputComponents;
+    uint32_t              maxFragmentOutputAttachments;
+    uint32_t              maxFragmentDualSrcAttachments;
+    uint32_t              maxFragmentCombinedOutputResources;
+    uint32_t              maxComputeSharedMemorySize;
+    uint32_t              maxComputeWorkGroupCount[3];
+    uint32_t              maxComputeWorkGroupInvocations;
+    uint32_t              maxComputeWorkGroupSize[3];
+    uint32_t              subPixelPrecisionBits;
+    uint32_t              subTexelPrecisionBits;
+    uint32_t              mipmapPrecisionBits;
+    uint32_t              maxDrawIndexedIndexValue;
+    uint32_t              maxDrawIndirectCount;
+    float                 maxSamplerLodBias;
+    float                 maxSamplerAnisotropy;
+    uint32_t              maxViewports;
+    uint32_t              maxViewportDimensions[2];
+    float                 viewportBoundsRange[2];
+    uint32_t              viewportSubPixelBits;
+    size_t                minMemoryMapAlignment;
+    VkDeviceSize          minTexelBufferOffsetAlignment;
+    VkDeviceSize          minUniformBufferOffsetAlignment;
+    VkDeviceSize          minStorageBufferOffsetAlignment;
+    int32_t               minTexelOffset;
+    uint32_t              maxTexelOffset;
+    int32_t               minTexelGatherOffset;
+    uint32_t              maxTexelGatherOffset;
+    float                 minInterpolationOffset;
+    float                 maxInterpolationOffset;
+    uint32_t              subPixelInterpolationOffsetBits;
+    uint32_t              maxFramebufferWidth;
+    uint32_t              maxFramebufferHeight;
+    uint32_t              maxFramebufferLayers;
+    VkSampleCountFlags    framebufferColorSampleCounts;
+    VkSampleCountFlags    framebufferDepthSampleCounts;
+    VkSampleCountFlags    framebufferStencilSampleCounts;
+    VkSampleCountFlags    framebufferNoAttachmentsSampleCounts;
+    uint32_t              maxColorAttachments;
+    VkSampleCountFlags    sampledImageColorSampleCounts;
+    VkSampleCountFlags    sampledImageIntegerSampleCounts;
+    VkSampleCountFlags    sampledImageDepthSampleCounts;
+    VkSampleCountFlags    sampledImageStencilSampleCounts;
+    VkSampleCountFlags    storageImageSampleCounts;
+    uint32_t              maxSampleMaskWords;
+    VkBool32              timestampComputeAndGraphics;
+    float                 timestampPeriod;
+    uint32_t              maxClipDistances;
+    uint32_t              maxCullDistances;
+    uint32_t              maxCombinedClipAndCullDistances;
+    uint32_t              discreteQueuePriorities;
+    float                 pointSizeRange[2];
+    float                 lineWidthRange[2];
+    float                 pointSizeGranularity;
+    float                 lineWidthGranularity;
+    VkBool32              strictLines;
+    VkBool32              standardSampleLocations;
+    VkDeviceSize          optimalBufferCopyOffsetAlignment;
+    VkDeviceSize          optimalBufferCopyRowPitchAlignment;
+    VkDeviceSize          nonCoherentAtomSize;
+} VkPhysicalDeviceLimits;
+
+typedef struct VkPhysicalDeviceSparseProperties {
+    VkBool32    residencyStandard2DBlockShape;
+    VkBool32    residencyStandard2DMultisampleBlockShape;
+    VkBool32    residencyStandard3DBlockShape;
+    VkBool32    residencyAlignedMipSize;
+    VkBool32    residencyNonResidentStrict;
+} VkPhysicalDeviceSparseProperties;
+
+typedef struct VkPhysicalDeviceProperties {
+    uint32_t                            apiVersion;
+    uint32_t                            driverVersion;
+    uint32_t                            vendorID;
+    uint32_t                            deviceID;
+    VkPhysicalDeviceType                deviceType;
+    char                                deviceName[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
+    uint8_t                             pipelineCacheUUID[VK_UUID_SIZE];
+    VkPhysicalDeviceLimits              limits;
+    VkPhysicalDeviceSparseProperties    sparseProperties;
+} VkPhysicalDeviceProperties;
+
+typedef struct VkQueueFamilyProperties {
+    VkQueueFlags    queueFlags;
+    uint32_t        queueCount;
+    uint32_t        timestampValidBits;
+    VkExtent3D      minImageTransferGranularity;
+} VkQueueFamilyProperties;
+
+typedef struct VkMemoryType {
+    VkMemoryPropertyFlags    propertyFlags;
+    uint32_t                 heapIndex;
+} VkMemoryType;
+
+typedef struct VkMemoryHeap {
+    VkDeviceSize         size;
+    VkMemoryHeapFlags    flags;
+} VkMemoryHeap;
+
+typedef struct VkPhysicalDeviceMemoryProperties {
+    uint32_t        memoryTypeCount;
+    VkMemoryType    memoryTypes[VK_MAX_MEMORY_TYPES];
+    uint32_t        memoryHeapCount;
+    VkMemoryHeap    memoryHeaps[VK_MAX_MEMORY_HEAPS];
+} VkPhysicalDeviceMemoryProperties;
+
+typedef struct VkDeviceQueueCreateInfo {
+    VkStructureType             sType;
+    const void*                 pNext;
+    VkDeviceQueueCreateFlags    flags;
+    uint32_t                    queueFamilyIndex;
+    uint32_t                    queueCount;
+    const float*                pQueuePriorities;
+} VkDeviceQueueCreateInfo;
+
+typedef struct VkDeviceCreateInfo {
+    VkStructureType                    sType;
+    const void*                        pNext;
+    VkDeviceCreateFlags                flags;
+    uint32_t                           queueCreateInfoCount;
+    const VkDeviceQueueCreateInfo*     pQueueCreateInfos;
+    uint32_t                           enabledLayerCount;
+    const char* const*                 ppEnabledLayerNames;
+    uint32_t                           enabledExtensionCount;
+    const char* const*                 ppEnabledExtensionNames;
+    const VkPhysicalDeviceFeatures*    pEnabledFeatures;
+} VkDeviceCreateInfo;
+
+typedef struct VkExtensionProperties {
+    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
+    uint32_t    specVersion;
+} VkExtensionProperties;
+
+typedef struct VkLayerProperties {
+    char        layerName[VK_MAX_EXTENSION_NAME_SIZE];
+    uint32_t    specVersion;
+    uint32_t    implementationVersion;
+    char        description[VK_MAX_DESCRIPTION_SIZE];
+} VkLayerProperties;
+
+typedef struct VkSubmitInfo {
+    VkStructureType                sType;
+    const void*                    pNext;
+    uint32_t                       waitSemaphoreCount;
+    const VkSemaphore*             pWaitSemaphores;
+    const VkPipelineStageFlags*    pWaitDstStageMask;
+    uint32_t                       commandBufferCount;
+    const VkCommandBuffer*         pCommandBuffers;
+    uint32_t                       signalSemaphoreCount;
+    const VkSemaphore*             pSignalSemaphores;
+} VkSubmitInfo;
+
+typedef struct VkMemoryAllocateInfo {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkDeviceSize       allocationSize;
+    uint32_t           memoryTypeIndex;
+} VkMemoryAllocateInfo;
+
+typedef struct VkMappedMemoryRange {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkDeviceMemory     memory;
+    VkDeviceSize       offset;
+    VkDeviceSize       size;
+} VkMappedMemoryRange;
+
+typedef struct VkMemoryRequirements {
+    VkDeviceSize    size;
+    VkDeviceSize    alignment;
+    uint32_t        memoryTypeBits;
+} VkMemoryRequirements;
+
+typedef struct VkSparseImageFormatProperties {
+    VkImageAspectFlags          aspectMask;
+    VkExtent3D                  imageGranularity;
+    VkSparseImageFormatFlags    flags;
+} VkSparseImageFormatProperties;
+
+typedef struct VkSparseImageMemoryRequirements {
+    VkSparseImageFormatProperties    formatProperties;
+    uint32_t                         imageMipTailFirstLod;
+    VkDeviceSize                     imageMipTailSize;
+    VkDeviceSize                     imageMipTailOffset;
+    VkDeviceSize                     imageMipTailStride;
+} VkSparseImageMemoryRequirements;
+
+typedef struct VkSparseMemoryBind {
+    VkDeviceSize               resourceOffset;
+    VkDeviceSize               size;
+    VkDeviceMemory             memory;
+    VkDeviceSize               memoryOffset;
+    VkSparseMemoryBindFlags    flags;
+} VkSparseMemoryBind;
+
+typedef struct VkSparseBufferMemoryBindInfo {
+    VkBuffer                     buffer;
+    uint32_t                     bindCount;
+    const VkSparseMemoryBind*    pBinds;
+} VkSparseBufferMemoryBindInfo;
+
+typedef struct VkSparseImageOpaqueMemoryBindInfo {
+    VkImage                      image;
+    uint32_t                     bindCount;
+    const VkSparseMemoryBind*    pBinds;
+} VkSparseImageOpaqueMemoryBindInfo;
+
+typedef struct VkImageSubresource {
+    VkImageAspectFlags    aspectMask;
+    uint32_t              mipLevel;
+    uint32_t              arrayLayer;
+} VkImageSubresource;
+
+typedef struct VkOffset3D {
+    int32_t    x;
+    int32_t    y;
+    int32_t    z;
+} VkOffset3D;
+
+typedef struct VkSparseImageMemoryBind {
+    VkImageSubresource         subresource;
+    VkOffset3D                 offset;
+    VkExtent3D                 extent;
+    VkDeviceMemory             memory;
+    VkDeviceSize               memoryOffset;
+    VkSparseMemoryBindFlags    flags;
+} VkSparseImageMemoryBind;
+
+typedef struct VkSparseImageMemoryBindInfo {
+    VkImage                           image;
+    uint32_t                          bindCount;
+    const VkSparseImageMemoryBind*    pBinds;
+} VkSparseImageMemoryBindInfo;
+
+typedef struct VkBindSparseInfo {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    uint32_t                                    waitSemaphoreCount;
+    const VkSemaphore*                          pWaitSemaphores;
+    uint32_t                                    bufferBindCount;
+    const VkSparseBufferMemoryBindInfo*         pBufferBinds;
+    uint32_t                                    imageOpaqueBindCount;
+    const VkSparseImageOpaqueMemoryBindInfo*    pImageOpaqueBinds;
+    uint32_t                                    imageBindCount;
+    const VkSparseImageMemoryBindInfo*          pImageBinds;
+    uint32_t                                    signalSemaphoreCount;
+    const VkSemaphore*                          pSignalSemaphores;
+} VkBindSparseInfo;
+
+typedef struct VkFenceCreateInfo {
+    VkStructureType       sType;
+    const void*           pNext;
+    VkFenceCreateFlags    flags;
+} VkFenceCreateInfo;
+
+typedef struct VkSemaphoreCreateInfo {
+    VkStructureType           sType;
+    const void*               pNext;
+    VkSemaphoreCreateFlags    flags;
+} VkSemaphoreCreateInfo;
+
+typedef struct VkEventCreateInfo {
+    VkStructureType       sType;
+    const void*           pNext;
+    VkEventCreateFlags    flags;
+} VkEventCreateInfo;
+
+typedef struct VkQueryPoolCreateInfo {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkQueryPoolCreateFlags           flags;
+    VkQueryType                      queryType;
+    uint32_t                         queryCount;
+    VkQueryPipelineStatisticFlags    pipelineStatistics;
+} VkQueryPoolCreateInfo;
+
+typedef struct VkBufferCreateInfo {
+    VkStructureType        sType;
+    const void*            pNext;
+    VkBufferCreateFlags    flags;
+    VkDeviceSize           size;
+    VkBufferUsageFlags     usage;
+    VkSharingMode          sharingMode;
+    uint32_t               queueFamilyIndexCount;
+    const uint32_t*        pQueueFamilyIndices;
+} VkBufferCreateInfo;
+
+typedef struct VkBufferViewCreateInfo {
+    VkStructureType            sType;
+    const void*                pNext;
+    VkBufferViewCreateFlags    flags;
+    VkBuffer                   buffer;
+    VkFormat                   format;
+    VkDeviceSize               offset;
+    VkDeviceSize               range;
+} VkBufferViewCreateInfo;
+
+typedef struct VkImageCreateInfo {
+    VkStructureType          sType;
+    const void*              pNext;
+    VkImageCreateFlags       flags;
+    VkImageType              imageType;
+    VkFormat                 format;
+    VkExtent3D               extent;
+    uint32_t                 mipLevels;
+    uint32_t                 arrayLayers;
+    VkSampleCountFlagBits    samples;
+    VkImageTiling            tiling;
+    VkImageUsageFlags        usage;
+    VkSharingMode            sharingMode;
+    uint32_t                 queueFamilyIndexCount;
+    const uint32_t*          pQueueFamilyIndices;
+    VkImageLayout            initialLayout;
+} VkImageCreateInfo;
+
+typedef struct VkSubresourceLayout {
+    VkDeviceSize    offset;
+    VkDeviceSize    size;
+    VkDeviceSize    rowPitch;
+    VkDeviceSize    arrayPitch;
+    VkDeviceSize    depthPitch;
+} VkSubresourceLayout;
+
+typedef struct VkComponentMapping {
+    VkComponentSwizzle    r;
+    VkComponentSwizzle    g;
+    VkComponentSwizzle    b;
+    VkComponentSwizzle    a;
+} VkComponentMapping;
+
+typedef struct VkImageSubresourceRange {
+    VkImageAspectFlags    aspectMask;
+    uint32_t              baseMipLevel;
+    uint32_t              levelCount;
+    uint32_t              baseArrayLayer;
+    uint32_t              layerCount;
+} VkImageSubresourceRange;
+
+typedef struct VkImageViewCreateInfo {
+    VkStructureType            sType;
+    const void*                pNext;
+    VkImageViewCreateFlags     flags;
+    VkImage                    image;
+    VkImageViewType            viewType;
+    VkFormat                   format;
+    VkComponentMapping         components;
+    VkImageSubresourceRange    subresourceRange;
+} VkImageViewCreateInfo;
+
+typedef struct VkShaderModuleCreateInfo {
+    VkStructureType              sType;
+    const void*                  pNext;
+    VkShaderModuleCreateFlags    flags;
+    size_t                       codeSize;
+    const uint32_t*              pCode;
+} VkShaderModuleCreateInfo;
+
+typedef struct VkPipelineCacheCreateInfo {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkPipelineCacheCreateFlags    flags;
+    size_t                        initialDataSize;
+    const void*                   pInitialData;
+} VkPipelineCacheCreateInfo;
+
+typedef struct VkSpecializationMapEntry {
+    uint32_t    constantID;
+    uint32_t    offset;
+    size_t      size;
+} VkSpecializationMapEntry;
+
+typedef struct VkSpecializationInfo {
+    uint32_t                           mapEntryCount;
+    const VkSpecializationMapEntry*    pMapEntries;
+    size_t                             dataSize;
+    const void*                        pData;
+} VkSpecializationInfo;
+
+typedef struct VkPipelineShaderStageCreateInfo {
+    VkStructureType                     sType;
+    const void*                         pNext;
+    VkPipelineShaderStageCreateFlags    flags;
+    VkShaderStageFlagBits               stage;
+    VkShaderModule                      module;
+    const char*                         pName;
+    const VkSpecializationInfo*         pSpecializationInfo;
+} VkPipelineShaderStageCreateInfo;
+
+typedef struct VkVertexInputBindingDescription {
+    uint32_t             binding;
+    uint32_t             stride;
+    VkVertexInputRate    inputRate;
+} VkVertexInputBindingDescription;
+
+typedef struct VkVertexInputAttributeDescription {
+    uint32_t    location;
+    uint32_t    binding;
+    VkFormat    format;
+    uint32_t    offset;
+} VkVertexInputAttributeDescription;
+
+typedef struct VkPipelineVertexInputStateCreateInfo {
+    VkStructureType                             sType;
+    const void*                                 pNext;
+    VkPipelineVertexInputStateCreateFlags       flags;
+    uint32_t                                    vertexBindingDescriptionCount;
+    const VkVertexInputBindingDescription*      pVertexBindingDescriptions;
+    uint32_t                                    vertexAttributeDescriptionCount;
+    const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions;
+} VkPipelineVertexInputStateCreateInfo;
+
+typedef struct VkPipelineInputAssemblyStateCreateInfo {
+    VkStructureType                            sType;
+    const void*                                pNext;
+    VkPipelineInputAssemblyStateCreateFlags    flags;
+    VkPrimitiveTopology                        topology;
+    VkBool32                                   primitiveRestartEnable;
+} VkPipelineInputAssemblyStateCreateInfo;
+
+typedef struct VkPipelineTessellationStateCreateInfo {
+    VkStructureType                           sType;
+    const void*                               pNext;
+    VkPipelineTessellationStateCreateFlags    flags;
+    uint32_t                                  patchControlPoints;
+} VkPipelineTessellationStateCreateInfo;
+
+typedef struct VkViewport {
+    float    x;
+    float    y;
+    float    width;
+    float    height;
+    float    minDepth;
+    float    maxDepth;
+} VkViewport;
+
+typedef struct VkOffset2D {
+    int32_t    x;
+    int32_t    y;
+} VkOffset2D;
+
+typedef struct VkExtent2D {
+    uint32_t    width;
+    uint32_t    height;
+} VkExtent2D;
+
+typedef struct VkRect2D {
+    VkOffset2D    offset;
+    VkExtent2D    extent;
+} VkRect2D;
+
+typedef struct VkPipelineViewportStateCreateInfo {
+    VkStructureType                       sType;
+    const void*                           pNext;
+    VkPipelineViewportStateCreateFlags    flags;
+    uint32_t                              viewportCount;
+    const VkViewport*                     pViewports;
+    uint32_t                              scissorCount;
+    const VkRect2D*                       pScissors;
+} VkPipelineViewportStateCreateInfo;
+
+typedef struct VkPipelineRasterizationStateCreateInfo {
+    VkStructureType                            sType;
+    const void*                                pNext;
+    VkPipelineRasterizationStateCreateFlags    flags;
+    VkBool32                                   depthClampEnable;
+    VkBool32                                   rasterizerDiscardEnable;
+    VkPolygonMode                              polygonMode;
+    VkCullModeFlags                            cullMode;
+    VkFrontFace                                frontFace;
+    VkBool32                                   depthBiasEnable;
+    float                                      depthBiasConstantFactor;
+    float                                      depthBiasClamp;
+    float                                      depthBiasSlopeFactor;
+    float                                      lineWidth;
+} VkPipelineRasterizationStateCreateInfo;
+
+typedef struct VkPipelineMultisampleStateCreateInfo {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkPipelineMultisampleStateCreateFlags    flags;
+    VkSampleCountFlagBits                    rasterizationSamples;
+    VkBool32                                 sampleShadingEnable;
+    float                                    minSampleShading;
+    const VkSampleMask*                      pSampleMask;
+    VkBool32                                 alphaToCoverageEnable;
+    VkBool32                                 alphaToOneEnable;
+} VkPipelineMultisampleStateCreateInfo;
+
+typedef struct VkStencilOpState {
+    VkStencilOp    failOp;
+    VkStencilOp    passOp;
+    VkStencilOp    depthFailOp;
+    VkCompareOp    compareOp;
+    uint32_t       compareMask;
+    uint32_t       writeMask;
+    uint32_t       reference;
+} VkStencilOpState;
+
+typedef struct VkPipelineDepthStencilStateCreateInfo {
+    VkStructureType                           sType;
+    const void*                               pNext;
+    VkPipelineDepthStencilStateCreateFlags    flags;
+    VkBool32                                  depthTestEnable;
+    VkBool32                                  depthWriteEnable;
+    VkCompareOp                               depthCompareOp;
+    VkBool32                                  depthBoundsTestEnable;
+    VkBool32                                  stencilTestEnable;
+    VkStencilOpState                          front;
+    VkStencilOpState                          back;
+    float                                     minDepthBounds;
+    float                                     maxDepthBounds;
+} VkPipelineDepthStencilStateCreateInfo;
+
+typedef struct VkPipelineColorBlendAttachmentState {
+    VkBool32                 blendEnable;
+    VkBlendFactor            srcColorBlendFactor;
+    VkBlendFactor            dstColorBlendFactor;
+    VkBlendOp                colorBlendOp;
+    VkBlendFactor            srcAlphaBlendFactor;
+    VkBlendFactor            dstAlphaBlendFactor;
+    VkBlendOp                alphaBlendOp;
+    VkColorComponentFlags    colorWriteMask;
+} VkPipelineColorBlendAttachmentState;
+
+typedef struct VkPipelineColorBlendStateCreateInfo {
+    VkStructureType                               sType;
+    const void*                                   pNext;
+    VkPipelineColorBlendStateCreateFlags          flags;
+    VkBool32                                      logicOpEnable;
+    VkLogicOp                                     logicOp;
+    uint32_t                                      attachmentCount;
+    const VkPipelineColorBlendAttachmentState*    pAttachments;
+    float                                         blendConstants[4];
+} VkPipelineColorBlendStateCreateInfo;
+
+typedef struct VkPipelineDynamicStateCreateInfo {
+    VkStructureType                      sType;
+    const void*                          pNext;
+    VkPipelineDynamicStateCreateFlags    flags;
+    uint32_t                             dynamicStateCount;
+    const VkDynamicState*                pDynamicStates;
+} VkPipelineDynamicStateCreateInfo;
+
+typedef struct VkGraphicsPipelineCreateInfo {
+    VkStructureType                                  sType;
+    const void*                                      pNext;
+    VkPipelineCreateFlags                            flags;
+    uint32_t                                         stageCount;
+    const VkPipelineShaderStageCreateInfo*           pStages;
+    const VkPipelineVertexInputStateCreateInfo*      pVertexInputState;
+    const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState;
+    const VkPipelineTessellationStateCreateInfo*     pTessellationState;
+    const VkPipelineViewportStateCreateInfo*         pViewportState;
+    const VkPipelineRasterizationStateCreateInfo*    pRasterizationState;
+    const VkPipelineMultisampleStateCreateInfo*      pMultisampleState;
+    const VkPipelineDepthStencilStateCreateInfo*     pDepthStencilState;
+    const VkPipelineColorBlendStateCreateInfo*       pColorBlendState;
+    const VkPipelineDynamicStateCreateInfo*          pDynamicState;
+    VkPipelineLayout                                 layout;
+    VkRenderPass                                     renderPass;
+    uint32_t                                         subpass;
+    VkPipeline                                       basePipelineHandle;
+    int32_t                                          basePipelineIndex;
+} VkGraphicsPipelineCreateInfo;
+
+typedef struct VkComputePipelineCreateInfo {
+    VkStructureType                    sType;
+    const void*                        pNext;
+    VkPipelineCreateFlags              flags;
+    VkPipelineShaderStageCreateInfo    stage;
+    VkPipelineLayout                   layout;
+    VkPipeline                         basePipelineHandle;
+    int32_t                            basePipelineIndex;
+} VkComputePipelineCreateInfo;
+
+typedef struct VkPushConstantRange {
+    VkShaderStageFlags    stageFlags;
+    uint32_t              offset;
+    uint32_t              size;
+} VkPushConstantRange;
+
+typedef struct VkPipelineLayoutCreateInfo {
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkPipelineLayoutCreateFlags     flags;
+    uint32_t                        setLayoutCount;
+    const VkDescriptorSetLayout*    pSetLayouts;
+    uint32_t                        pushConstantRangeCount;
+    const VkPushConstantRange*      pPushConstantRanges;
+} VkPipelineLayoutCreateInfo;
+
+typedef struct VkSamplerCreateInfo {
+    VkStructureType         sType;
+    const void*             pNext;
+    VkSamplerCreateFlags    flags;
+    VkFilter                magFilter;
+    VkFilter                minFilter;
+    VkSamplerMipmapMode     mipmapMode;
+    VkSamplerAddressMode    addressModeU;
+    VkSamplerAddressMode    addressModeV;
+    VkSamplerAddressMode    addressModeW;
+    float                   mipLodBias;
+    VkBool32                anisotropyEnable;
+    float                   maxAnisotropy;
+    VkBool32                compareEnable;
+    VkCompareOp             compareOp;
+    float                   minLod;
+    float                   maxLod;
+    VkBorderColor           borderColor;
+    VkBool32                unnormalizedCoordinates;
+} VkSamplerCreateInfo;
+
+typedef struct VkDescriptorSetLayoutBinding {
+    uint32_t              binding;
+    VkDescriptorType      descriptorType;
+    uint32_t              descriptorCount;
+    VkShaderStageFlags    stageFlags;
+    const VkSampler*      pImmutableSamplers;
+} VkDescriptorSetLayoutBinding;
+
+typedef struct VkDescriptorSetLayoutCreateInfo {
+    VkStructureType                        sType;
+    const void*                            pNext;
+    VkDescriptorSetLayoutCreateFlags       flags;
+    uint32_t                               bindingCount;
+    const VkDescriptorSetLayoutBinding*    pBindings;
+} VkDescriptorSetLayoutCreateInfo;
+
+typedef struct VkDescriptorPoolSize {
+    VkDescriptorType    type;
+    uint32_t            descriptorCount;
+} VkDescriptorPoolSize;
+
+typedef struct VkDescriptorPoolCreateInfo {
+    VkStructureType                sType;
+    const void*                    pNext;
+    VkDescriptorPoolCreateFlags    flags;
+    uint32_t                       maxSets;
+    uint32_t                       poolSizeCount;
+    const VkDescriptorPoolSize*    pPoolSizes;
+} VkDescriptorPoolCreateInfo;
+
+typedef struct VkDescriptorSetAllocateInfo {
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkDescriptorPool                descriptorPool;
+    uint32_t                        descriptorSetCount;
+    const VkDescriptorSetLayout*    pSetLayouts;
+} VkDescriptorSetAllocateInfo;
+
+typedef struct VkDescriptorImageInfo {
+    VkSampler        sampler;
+    VkImageView      imageView;
+    VkImageLayout    imageLayout;
+} VkDescriptorImageInfo;
+
+typedef struct VkDescriptorBufferInfo {
+    VkBuffer        buffer;
+    VkDeviceSize    offset;
+    VkDeviceSize    range;
+} VkDescriptorBufferInfo;
+
+typedef struct VkWriteDescriptorSet {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkDescriptorSet                  dstSet;
+    uint32_t                         dstBinding;
+    uint32_t                         dstArrayElement;
+    uint32_t                         descriptorCount;
+    VkDescriptorType                 descriptorType;
+    const VkDescriptorImageInfo*     pImageInfo;
+    const VkDescriptorBufferInfo*    pBufferInfo;
+    const VkBufferView*              pTexelBufferView;
+} VkWriteDescriptorSet;
+
+typedef struct VkCopyDescriptorSet {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkDescriptorSet    srcSet;
+    uint32_t           srcBinding;
+    uint32_t           srcArrayElement;
+    VkDescriptorSet    dstSet;
+    uint32_t           dstBinding;
+    uint32_t           dstArrayElement;
+    uint32_t           descriptorCount;
+} VkCopyDescriptorSet;
+
+typedef struct VkFramebufferCreateInfo {
+    VkStructureType             sType;
+    const void*                 pNext;
+    VkFramebufferCreateFlags    flags;
+    VkRenderPass                renderPass;
+    uint32_t                    attachmentCount;
+    const VkImageView*          pAttachments;
+    uint32_t                    width;
+    uint32_t                    height;
+    uint32_t                    layers;
+} VkFramebufferCreateInfo;
+
+typedef struct VkAttachmentDescription {
+    VkAttachmentDescriptionFlags    flags;
+    VkFormat                        format;
+    VkSampleCountFlagBits           samples;
+    VkAttachmentLoadOp              loadOp;
+    VkAttachmentStoreOp             storeOp;
+    VkAttachmentLoadOp              stencilLoadOp;
+    VkAttachmentStoreOp             stencilStoreOp;
+    VkImageLayout                   initialLayout;
+    VkImageLayout                   finalLayout;
+} VkAttachmentDescription;
+
+typedef struct VkAttachmentReference {
+    uint32_t         attachment;
+    VkImageLayout    layout;
+} VkAttachmentReference;
+
+typedef struct VkSubpassDescription {
+    VkSubpassDescriptionFlags       flags;
+    VkPipelineBindPoint             pipelineBindPoint;
+    uint32_t                        inputAttachmentCount;
+    const VkAttachmentReference*    pInputAttachments;
+    uint32_t                        colorAttachmentCount;
+    const VkAttachmentReference*    pColorAttachments;
+    const VkAttachmentReference*    pResolveAttachments;
+    const VkAttachmentReference*    pDepthStencilAttachment;
+    uint32_t                        preserveAttachmentCount;
+    const uint32_t*                 pPreserveAttachments;
+} VkSubpassDescription;
+
+typedef struct VkSubpassDependency {
+    uint32_t                srcSubpass;
+    uint32_t                dstSubpass;
+    VkPipelineStageFlags    srcStageMask;
+    VkPipelineStageFlags    dstStageMask;
+    VkAccessFlags           srcAccessMask;
+    VkAccessFlags           dstAccessMask;
+    VkDependencyFlags       dependencyFlags;
+} VkSubpassDependency;
+
+typedef struct VkRenderPassCreateInfo {
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkRenderPassCreateFlags           flags;
+    uint32_t                          attachmentCount;
+    const VkAttachmentDescription*    pAttachments;
+    uint32_t                          subpassCount;
+    const VkSubpassDescription*       pSubpasses;
+    uint32_t                          dependencyCount;
+    const VkSubpassDependency*        pDependencies;
+} VkRenderPassCreateInfo;
+
+typedef struct VkCommandPoolCreateInfo {
+    VkStructureType             sType;
+    const void*                 pNext;
+    VkCommandPoolCreateFlags    flags;
+    uint32_t                    queueFamilyIndex;
+} VkCommandPoolCreateInfo;
+
+typedef struct VkCommandBufferAllocateInfo {
+    VkStructureType         sType;
+    const void*             pNext;
+    VkCommandPool           commandPool;
+    VkCommandBufferLevel    level;
+    uint32_t                commandBufferCount;
+} VkCommandBufferAllocateInfo;
+
+typedef struct VkCommandBufferInheritanceInfo {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkRenderPass                     renderPass;
+    uint32_t                         subpass;
+    VkFramebuffer                    framebuffer;
+    VkBool32                         occlusionQueryEnable;
+    VkQueryControlFlags              queryFlags;
+    VkQueryPipelineStatisticFlags    pipelineStatistics;
+} VkCommandBufferInheritanceInfo;
+
+typedef struct VkCommandBufferBeginInfo {
+    VkStructureType                          sType;
+    const void*                              pNext;
+    VkCommandBufferUsageFlags                flags;
+    const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
+} VkCommandBufferBeginInfo;
+
+typedef struct VkBufferCopy {
+    VkDeviceSize    srcOffset;
+    VkDeviceSize    dstOffset;
+    VkDeviceSize    size;
+} VkBufferCopy;
+
+typedef struct VkImageSubresourceLayers {
+    VkImageAspectFlags    aspectMask;
+    uint32_t              mipLevel;
+    uint32_t              baseArrayLayer;
+    uint32_t              layerCount;
+} VkImageSubresourceLayers;
+
+typedef struct VkImageCopy {
+    VkImageSubresourceLayers    srcSubresource;
+    VkOffset3D                  srcOffset;
+    VkImageSubresourceLayers    dstSubresource;
+    VkOffset3D                  dstOffset;
+    VkExtent3D                  extent;
+} VkImageCopy;
+
+typedef struct VkImageBlit {
+    VkImageSubresourceLayers    srcSubresource;
+    VkOffset3D                  srcOffsets[2];
+    VkImageSubresourceLayers    dstSubresource;
+    VkOffset3D                  dstOffsets[2];
+} VkImageBlit;
+
+typedef struct VkBufferImageCopy {
+    VkDeviceSize                bufferOffset;
+    uint32_t                    bufferRowLength;
+    uint32_t                    bufferImageHeight;
+    VkImageSubresourceLayers    imageSubresource;
+    VkOffset3D                  imageOffset;
+    VkExtent3D                  imageExtent;
+} VkBufferImageCopy;
+
+typedef union VkClearColorValue {
+    float       float32[4];
+    int32_t     int32[4];
+    uint32_t    uint32[4];
+} VkClearColorValue;
+
+typedef struct VkClearDepthStencilValue {
+    float       depth;
+    uint32_t    stencil;
+} VkClearDepthStencilValue;
+
+typedef union VkClearValue {
+    VkClearColorValue           color;
+    VkClearDepthStencilValue    depthStencil;
+} VkClearValue;
+
+typedef struct VkClearAttachment {
+    VkImageAspectFlags    aspectMask;
+    uint32_t              colorAttachment;
+    VkClearValue          clearValue;
+} VkClearAttachment;
+
+typedef struct VkClearRect {
+    VkRect2D    rect;
+    uint32_t    baseArrayLayer;
+    uint32_t    layerCount;
+} VkClearRect;
+
+typedef struct VkImageResolve {
+    VkImageSubresourceLayers    srcSubresource;
+    VkOffset3D                  srcOffset;
+    VkImageSubresourceLayers    dstSubresource;
+    VkOffset3D                  dstOffset;
+    VkExtent3D                  extent;
+} VkImageResolve;
+
+typedef struct VkMemoryBarrier {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkAccessFlags      srcAccessMask;
+    VkAccessFlags      dstAccessMask;
+} VkMemoryBarrier;
+
+typedef struct VkBufferMemoryBarrier {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkAccessFlags      srcAccessMask;
+    VkAccessFlags      dstAccessMask;
+    uint32_t           srcQueueFamilyIndex;
+    uint32_t           dstQueueFamilyIndex;
+    VkBuffer           buffer;
+    VkDeviceSize       offset;
+    VkDeviceSize       size;
+} VkBufferMemoryBarrier;
+
+typedef struct VkImageMemoryBarrier {
+    VkStructureType            sType;
+    const void*                pNext;
+    VkAccessFlags              srcAccessMask;
+    VkAccessFlags              dstAccessMask;
+    VkImageLayout              oldLayout;
+    VkImageLayout              newLayout;
+    uint32_t                   srcQueueFamilyIndex;
+    uint32_t                   dstQueueFamilyIndex;
+    VkImage                    image;
+    VkImageSubresourceRange    subresourceRange;
+} VkImageMemoryBarrier;
+
+typedef struct VkRenderPassBeginInfo {
+    VkStructureType        sType;
+    const void*            pNext;
+    VkRenderPass           renderPass;
+    VkFramebuffer          framebuffer;
+    VkRect2D               renderArea;
+    uint32_t               clearValueCount;
+    const VkClearValue*    pClearValues;
+} VkRenderPassBeginInfo;
+
+typedef struct VkDispatchIndirectCommand {
+    uint32_t    x;
+    uint32_t    y;
+    uint32_t    z;
+} VkDispatchIndirectCommand;
+
+typedef struct VkDrawIndexedIndirectCommand {
+    uint32_t    indexCount;
+    uint32_t    instanceCount;
+    uint32_t    firstIndex;
+    int32_t     vertexOffset;
+    uint32_t    firstInstance;
+} VkDrawIndexedIndirectCommand;
+
+typedef struct VkDrawIndirectCommand {
+    uint32_t    vertexCount;
+    uint32_t    instanceCount;
+    uint32_t    firstVertex;
+    uint32_t    firstInstance;
+} VkDrawIndirectCommand;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateInstance)(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+typedef void (VKAPI_PTR *PFN_vkDestroyInstance)(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumeratePhysicalDevices)(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFeatures)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceQueueFamilyProperties)(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceMemoryProperties)(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetInstanceProcAddr)(VkInstance instance, const char* pName);
+typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_vkGetDeviceProcAddr)(VkDevice device, const char* pName);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDevice)(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+typedef void (VKAPI_PTR *PFN_vkDestroyDevice)(VkDevice device, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceExtensionProperties)(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceExtensionProperties)(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateInstanceLayerProperties)(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkEnumerateDeviceLayerProperties)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceQueue)(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueSubmit)(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueWaitIdle)(VkQueue queue);
+typedef VkResult (VKAPI_PTR *PFN_vkDeviceWaitIdle)(VkDevice device);
+typedef VkResult (VKAPI_PTR *PFN_vkAllocateMemory)(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory);
+typedef void (VKAPI_PTR *PFN_vkFreeMemory)(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkMapMemory)(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
+typedef void (VKAPI_PTR *PFN_vkUnmapMemory)(VkDevice device, VkDeviceMemory memory);
+typedef VkResult (VKAPI_PTR *PFN_vkFlushMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+typedef VkResult (VKAPI_PTR *PFN_vkInvalidateMappedMemoryRanges)(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+typedef void (VKAPI_PTR *PFN_vkGetDeviceMemoryCommitment)(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
+typedef VkResult (VKAPI_PTR *PFN_vkBindBufferMemory)(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef VkResult (VKAPI_PTR *PFN_vkBindImageMemory)(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+typedef void (VKAPI_PTR *PFN_vkGetBufferMemoryRequirements)(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageMemoryRequirements)(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetImageSparseMemoryRequirements)(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+typedef void (VKAPI_PTR *PFN_vkGetPhysicalDeviceSparseImageFormatProperties)(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkQueueBindSparse)(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateFence)(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+typedef void (VKAPI_PTR *PFN_vkDestroyFence)(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkResetFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences);
+typedef VkResult (VKAPI_PTR *PFN_vkGetFenceStatus)(VkDevice device, VkFence fence);
+typedef VkResult (VKAPI_PTR *PFN_vkWaitForFences)(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSemaphore)(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore);
+typedef void (VKAPI_PTR *PFN_vkDestroySemaphore)(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateEvent)(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent);
+typedef void (VKAPI_PTR *PFN_vkDestroyEvent)(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetEventStatus)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI_PTR *PFN_vkSetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI_PTR *PFN_vkResetEvent)(VkDevice device, VkEvent event);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateQueryPool)(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool);
+typedef void (VKAPI_PTR *PFN_vkDestroyQueryPool)(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetQueryPoolResults)(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateBuffer)(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer);
+typedef void (VKAPI_PTR *PFN_vkDestroyBuffer)(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateBufferView)(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView);
+typedef void (VKAPI_PTR *PFN_vkDestroyBufferView)(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateImage)(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage);
+typedef void (VKAPI_PTR *PFN_vkDestroyImage)(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetImageSubresourceLayout)(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateImageView)(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView);
+typedef void (VKAPI_PTR *PFN_vkDestroyImageView)(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateShaderModule)(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule);
+typedef void (VKAPI_PTR *PFN_vkDestroyShaderModule)(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineCache)(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache);
+typedef void (VKAPI_PTR *PFN_vkDestroyPipelineCache)(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPipelineCacheData)(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData);
+typedef VkResult (VKAPI_PTR *PFN_vkMergePipelineCaches)(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateGraphicsPipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateComputePipelines)(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+typedef void (VKAPI_PTR *PFN_vkDestroyPipeline)(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreatePipelineLayout)(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyPipelineLayout)(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSampler)(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler);
+typedef void (VKAPI_PTR *PFN_vkDestroySampler)(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorSetLayout)(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorSetLayout)(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDescriptorPool)(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool);
+typedef void (VKAPI_PTR *PFN_vkDestroyDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkResetDescriptorPool)(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags);
+typedef VkResult (VKAPI_PTR *PFN_vkAllocateDescriptorSets)(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets);
+typedef VkResult (VKAPI_PTR *PFN_vkFreeDescriptorSets)(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets);
+typedef void (VKAPI_PTR *PFN_vkUpdateDescriptorSets)(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateFramebuffer)(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer);
+typedef void (VKAPI_PTR *PFN_vkDestroyFramebuffer)(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateRenderPass)(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+typedef void (VKAPI_PTR *PFN_vkDestroyRenderPass)(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkGetRenderAreaGranularity)(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateCommandPool)(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
+typedef void (VKAPI_PTR *PFN_vkDestroyCommandPool)(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkResetCommandPool)(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
+typedef VkResult (VKAPI_PTR *PFN_vkAllocateCommandBuffers)(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
+typedef void (VKAPI_PTR *PFN_vkFreeCommandBuffers)(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+typedef VkResult (VKAPI_PTR *PFN_vkBeginCommandBuffer)(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo);
+typedef VkResult (VKAPI_PTR *PFN_vkEndCommandBuffer)(VkCommandBuffer commandBuffer);
+typedef VkResult (VKAPI_PTR *PFN_vkResetCommandBuffer)(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags);
+typedef void (VKAPI_PTR *PFN_vkCmdBindPipeline)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+typedef void (VKAPI_PTR *PFN_vkCmdSetViewport)(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports);
+typedef void (VKAPI_PTR *PFN_vkCmdSetScissor)(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors);
+typedef void (VKAPI_PTR *PFN_vkCmdSetLineWidth)(VkCommandBuffer commandBuffer, float lineWidth);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBias)(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
+typedef void (VKAPI_PTR *PFN_vkCmdSetBlendConstants)(VkCommandBuffer commandBuffer, const float blendConstants[4]);
+typedef void (VKAPI_PTR *PFN_vkCmdSetDepthBounds)(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds);
+typedef void (VKAPI_PTR *PFN_vkCmdSetStencilCompareMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask);
+typedef void (VKAPI_PTR *PFN_vkCmdSetStencilWriteMask)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask);
+typedef void (VKAPI_PTR *PFN_vkCmdSetStencilReference)(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference);
+typedef void (VKAPI_PTR *PFN_vkCmdBindDescriptorSets)(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets);
+typedef void (VKAPI_PTR *PFN_vkCmdBindIndexBuffer)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+typedef void (VKAPI_PTR *PFN_vkCmdBindVertexBuffers)(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
+typedef void (VKAPI_PTR *PFN_vkCmdDraw)(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexed)(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDrawIndexedIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatch)(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z);
+typedef void (VKAPI_PTR *PFN_vkCmdDispatchIndirect)(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyBuffer)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdBlitImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyBufferToImage)(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyImageToBuffer)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdUpdateBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t* pData);
+typedef void (VKAPI_PTR *PFN_vkCmdFillBuffer)(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data);
+typedef void (VKAPI_PTR *PFN_vkCmdClearColorImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+typedef void (VKAPI_PTR *PFN_vkCmdClearDepthStencilImage)(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+typedef void (VKAPI_PTR *PFN_vkCmdClearAttachments)(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects);
+typedef void (VKAPI_PTR *PFN_vkCmdResolveImage)(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions);
+typedef void (VKAPI_PTR *PFN_vkCmdSetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (VKAPI_PTR *PFN_vkCmdResetEvent)(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+typedef void (VKAPI_PTR *PFN_vkCmdWaitEvents)(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
+typedef void (VKAPI_PTR *PFN_vkCmdPipelineBarrier)(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
+typedef void (VKAPI_PTR *PFN_vkCmdEndQuery)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query);
+typedef void (VKAPI_PTR *PFN_vkCmdResetQueryPool)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+typedef void (VKAPI_PTR *PFN_vkCmdWriteTimestamp)(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query);
+typedef void (VKAPI_PTR *PFN_vkCmdCopyQueryPoolResults)(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
+typedef void (VKAPI_PTR *PFN_vkCmdPushConstants)(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
+typedef void (VKAPI_PTR *PFN_vkCmdBeginRenderPass)(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents);
+typedef void (VKAPI_PTR *PFN_vkCmdNextSubpass)(VkCommandBuffer commandBuffer, VkSubpassContents contents);
+typedef void (VKAPI_PTR *PFN_vkCmdEndRenderPass)(VkCommandBuffer commandBuffer);
+typedef void (VKAPI_PTR *PFN_vkCmdExecuteCommands)(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
+    const VkInstanceCreateInfo*                 pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkInstance*                                 pInstance);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(
+    VkInstance                                  instance,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
+    VkInstance                                  instance,
+    uint32_t*                                   pPhysicalDeviceCount,
+    VkPhysicalDevice*                           pPhysicalDevices);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceFeatures*                   pFeatures);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkFormatProperties*                         pFormatProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceImageFormatProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkImageType                                 type,
+    VkImageTiling                               tiling,
+    VkImageUsageFlags                           usage,
+    VkImageCreateFlags                          flags,
+    VkImageFormatProperties*                    pImageFormatProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceProperties*                 pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceQueueFamilyProperties(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pQueueFamilyPropertyCount,
+    VkQueueFamilyProperties*                    pQueueFamilyProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkPhysicalDeviceMemoryProperties*           pMemoryProperties);
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(
+    VkInstance                                  instance,
+    const char*                                 pName);
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(
+    VkDevice                                    device,
+    const char*                                 pName);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(
+    VkPhysicalDevice                            physicalDevice,
+    const VkDeviceCreateInfo*                   pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDevice*                                   pDevice);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(
+    VkDevice                                    device,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
+    const char*                                 pLayerName,
+    uint32_t*                                   pPropertyCount,
+    VkExtensionProperties*                      pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(
+    VkPhysicalDevice                            physicalDevice,
+    const char*                                 pLayerName,
+    uint32_t*                                   pPropertyCount,
+    VkExtensionProperties*                      pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
+    uint32_t*                                   pPropertyCount,
+    VkLayerProperties*                          pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pPropertyCount,
+    VkLayerProperties*                          pProperties);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(
+    VkDevice                                    device,
+    uint32_t                                    queueFamilyIndex,
+    uint32_t                                    queueIndex,
+    VkQueue*                                    pQueue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(
+    VkQueue                                     queue,
+    uint32_t                                    submitCount,
+    const VkSubmitInfo*                         pSubmits,
+    VkFence                                     fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(
+    VkQueue                                     queue);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(
+    VkDevice                                    device);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(
+    VkDevice                                    device,
+    const VkMemoryAllocateInfo*                 pAllocateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDeviceMemory*                             pMemory);
+
+VKAPI_ATTR void VKAPI_CALL vkFreeMemory(
+    VkDevice                                    device,
+    VkDeviceMemory                              memory,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(
+    VkDevice                                    device,
+    VkDeviceMemory                              memory,
+    VkDeviceSize                                offset,
+    VkDeviceSize                                size,
+    VkMemoryMapFlags                            flags,
+    void**                                      ppData);
+
+VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(
+    VkDevice                                    device,
+    VkDeviceMemory                              memory);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges(
+    VkDevice                                    device,
+    uint32_t                                    memoryRangeCount,
+    const VkMappedMemoryRange*                  pMemoryRanges);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges(
+    VkDevice                                    device,
+    uint32_t                                    memoryRangeCount,
+    const VkMappedMemoryRange*                  pMemoryRanges);
+
+VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment(
+    VkDevice                                    device,
+    VkDeviceMemory                              memory,
+    VkDeviceSize*                               pCommittedMemoryInBytes);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(
+    VkDevice                                    device,
+    VkBuffer                                    buffer,
+    VkDeviceMemory                              memory,
+    VkDeviceSize                                memoryOffset);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(
+    VkDevice                                    device,
+    VkImage                                     image,
+    VkDeviceMemory                              memory,
+    VkDeviceSize                                memoryOffset);
+
+VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements(
+    VkDevice                                    device,
+    VkBuffer                                    buffer,
+    VkMemoryRequirements*                       pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(
+    VkDevice                                    device,
+    VkImage                                     image,
+    VkMemoryRequirements*                       pMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSparseMemoryRequirements(
+    VkDevice                                    device,
+    VkImage                                     image,
+    uint32_t*                                   pSparseMemoryRequirementCount,
+    VkSparseImageMemoryRequirements*            pSparseMemoryRequirements);
+
+VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceSparseImageFormatProperties(
+    VkPhysicalDevice                            physicalDevice,
+    VkFormat                                    format,
+    VkImageType                                 type,
+    VkSampleCountFlagBits                       samples,
+    VkImageUsageFlags                           usage,
+    VkImageTiling                               tiling,
+    uint32_t*                                   pPropertyCount,
+    VkSparseImageFormatProperties*              pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse(
+    VkQueue                                     queue,
+    uint32_t                                    bindInfoCount,
+    const VkBindSparseInfo*                     pBindInfo,
+    VkFence                                     fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence(
+    VkDevice                                    device,
+    const VkFenceCreateInfo*                    pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkFence*                                    pFence);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyFence(
+    VkDevice                                    device,
+    VkFence                                     fence,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(
+    VkDevice                                    device,
+    uint32_t                                    fenceCount,
+    const VkFence*                              pFences);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(
+    VkDevice                                    device,
+    VkFence                                     fence);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(
+    VkDevice                                    device,
+    uint32_t                                    fenceCount,
+    const VkFence*                              pFences,
+    VkBool32                                    waitAll,
+    uint64_t                                    timeout);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(
+    VkDevice                                    device,
+    const VkSemaphoreCreateInfo*                pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSemaphore*                                pSemaphore);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(
+    VkDevice                                    device,
+    VkSemaphore                                 semaphore,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(
+    VkDevice                                    device,
+    const VkEventCreateInfo*                    pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkEvent*                                    pEvent);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(
+    VkDevice                                    device,
+    VkEvent                                     event,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(
+    VkDevice                                    device,
+    VkEvent                                     event);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(
+    VkDevice                                    device,
+    const VkQueryPoolCreateInfo*                pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkQueryPool*                                pQueryPool);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool(
+    VkDevice                                    device,
+    VkQueryPool                                 queryPool,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(
+    VkDevice                                    device,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    firstQuery,
+    uint32_t                                    queryCount,
+    size_t                                      dataSize,
+    void*                                       pData,
+    VkDeviceSize                                stride,
+    VkQueryResultFlags                          flags);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(
+    VkDevice                                    device,
+    const VkBufferCreateInfo*                   pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkBuffer*                                   pBuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer(
+    VkDevice                                    device,
+    VkBuffer                                    buffer,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(
+    VkDevice                                    device,
+    const VkBufferViewCreateInfo*               pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkBufferView*                               pView);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(
+    VkDevice                                    device,
+    VkBufferView                                bufferView,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(
+    VkDevice                                    device,
+    const VkImageCreateInfo*                    pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkImage*                                    pImage);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyImage(
+    VkDevice                                    device,
+    VkImage                                     image,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(
+    VkDevice                                    device,
+    VkImage                                     image,
+    const VkImageSubresource*                   pSubresource,
+    VkSubresourceLayout*                        pLayout);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(
+    VkDevice                                    device,
+    const VkImageViewCreateInfo*                pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkImageView*                                pView);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(
+    VkDevice                                    device,
+    VkImageView                                 imageView,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(
+    VkDevice                                    device,
+    const VkShaderModuleCreateInfo*             pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkShaderModule*                             pShaderModule);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule(
+    VkDevice                                    device,
+    VkShaderModule                              shaderModule,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(
+    VkDevice                                    device,
+    const VkPipelineCacheCreateInfo*            pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkPipelineCache*                            pPipelineCache);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    size_t*                                     pDataSize,
+    void*                                       pData);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(
+    VkDevice                                    device,
+    VkPipelineCache                             dstCache,
+    uint32_t                                    srcCacheCount,
+    const VkPipelineCache*                      pSrcCaches);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateGraphicsPipelines(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    uint32_t                                    createInfoCount,
+    const VkGraphicsPipelineCreateInfo*         pCreateInfos,
+    const VkAllocationCallbacks*                pAllocator,
+    VkPipeline*                                 pPipelines);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateComputePipelines(
+    VkDevice                                    device,
+    VkPipelineCache                             pipelineCache,
+    uint32_t                                    createInfoCount,
+    const VkComputePipelineCreateInfo*          pCreateInfos,
+    const VkAllocationCallbacks*                pAllocator,
+    VkPipeline*                                 pPipelines);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(
+    VkDevice                                    device,
+    VkPipeline                                  pipeline,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineLayout(
+    VkDevice                                    device,
+    const VkPipelineLayoutCreateInfo*           pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkPipelineLayout*                           pPipelineLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout(
+    VkDevice                                    device,
+    VkPipelineLayout                            pipelineLayout,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(
+    VkDevice                                    device,
+    const VkSamplerCreateInfo*                  pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSampler*                                  pSampler);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySampler(
+    VkDevice                                    device,
+    VkSampler                                   sampler,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorSetLayout(
+    VkDevice                                    device,
+    const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDescriptorSetLayout*                      pSetLayout);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorSetLayout(
+    VkDevice                                    device,
+    VkDescriptorSetLayout                       descriptorSetLayout,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDescriptorPool(
+    VkDevice                                    device,
+    const VkDescriptorPoolCreateInfo*           pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDescriptorPool*                           pDescriptorPool);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool,
+    VkDescriptorPoolResetFlags                  flags);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAllocateDescriptorSets(
+    VkDevice                                    device,
+    const VkDescriptorSetAllocateInfo*          pAllocateInfo,
+    VkDescriptorSet*                            pDescriptorSets);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(
+    VkDevice                                    device,
+    VkDescriptorPool                            descriptorPool,
+    uint32_t                                    descriptorSetCount,
+    const VkDescriptorSet*                      pDescriptorSets);
+
+VKAPI_ATTR void VKAPI_CALL vkUpdateDescriptorSets(
+    VkDevice                                    device,
+    uint32_t                                    descriptorWriteCount,
+    const VkWriteDescriptorSet*                 pDescriptorWrites,
+    uint32_t                                    descriptorCopyCount,
+    const VkCopyDescriptorSet*                  pDescriptorCopies);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(
+    VkDevice                                    device,
+    const VkFramebufferCreateInfo*              pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkFramebuffer*                              pFramebuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer(
+    VkDevice                                    device,
+    VkFramebuffer                               framebuffer,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(
+    VkDevice                                    device,
+    const VkRenderPassCreateInfo*               pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkRenderPass*                               pRenderPass);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(
+    VkDevice                                    device,
+    VkRenderPass                                renderPass,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity(
+    VkDevice                                    device,
+    VkRenderPass                                renderPass,
+    VkExtent2D*                                 pGranularity);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(
+    VkDevice                                    device,
+    const VkCommandPoolCreateInfo*              pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkCommandPool*                              pCommandPool);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(
+    VkDevice                                    device,
+    VkCommandPool                               commandPool,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool(
+    VkDevice                                    device,
+    VkCommandPool                               commandPool,
+    VkCommandPoolResetFlags                     flags);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(
+    VkDevice                                    device,
+    const VkCommandBufferAllocateInfo*          pAllocateInfo,
+    VkCommandBuffer*                            pCommandBuffers);
+
+VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(
+    VkDevice                                    device,
+    VkCommandPool                               commandPool,
+    uint32_t                                    commandBufferCount,
+    const VkCommandBuffer*                      pCommandBuffers);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkBeginCommandBuffer(
+    VkCommandBuffer                             commandBuffer,
+    const VkCommandBufferBeginInfo*             pBeginInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(
+    VkCommandBuffer                             commandBuffer);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkCommandBufferResetFlags                   flags);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline(
+    VkCommandBuffer                             commandBuffer,
+    VkPipelineBindPoint                         pipelineBindPoint,
+    VkPipeline                                  pipeline);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    firstViewport,
+    uint32_t                                    viewportCount,
+    const VkViewport*                           pViewports);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    firstScissor,
+    uint32_t                                    scissorCount,
+    const VkRect2D*                             pScissors);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(
+    VkCommandBuffer                             commandBuffer,
+    float                                       lineWidth);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias(
+    VkCommandBuffer                             commandBuffer,
+    float                                       depthBiasConstantFactor,
+    float                                       depthBiasClamp,
+    float                                       depthBiasSlopeFactor);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(
+    VkCommandBuffer                             commandBuffer,
+    const float                                 blendConstants[4]);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds(
+    VkCommandBuffer                             commandBuffer,
+    float                                       minDepthBounds,
+    float                                       maxDepthBounds);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask(
+    VkCommandBuffer                             commandBuffer,
+    VkStencilFaceFlags                          faceMask,
+    uint32_t                                    compareMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask(
+    VkCommandBuffer                             commandBuffer,
+    VkStencilFaceFlags                          faceMask,
+    uint32_t                                    writeMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference(
+    VkCommandBuffer                             commandBuffer,
+    VkStencilFaceFlags                          faceMask,
+    uint32_t                                    reference);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindDescriptorSets(
+    VkCommandBuffer                             commandBuffer,
+    VkPipelineBindPoint                         pipelineBindPoint,
+    VkPipelineLayout                            layout,
+    uint32_t                                    firstSet,
+    uint32_t                                    descriptorSetCount,
+    const VkDescriptorSet*                      pDescriptorSets,
+    uint32_t                                    dynamicOffsetCount,
+    const uint32_t*                             pDynamicOffsets);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    VkIndexType                                 indexType);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    firstBinding,
+    uint32_t                                    bindingCount,
+    const VkBuffer*                             pBuffers,
+    const VkDeviceSize*                         pOffsets);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDraw(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    vertexCount,
+    uint32_t                                    instanceCount,
+    uint32_t                                    firstVertex,
+    uint32_t                                    firstInstance);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    indexCount,
+    uint32_t                                    instanceCount,
+    uint32_t                                    firstIndex,
+    int32_t                                     vertexOffset,
+    uint32_t                                    firstInstance);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    uint32_t                                    drawCount,
+    uint32_t                                    stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset,
+    uint32_t                                    drawCount,
+    uint32_t                                    stride);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    x,
+    uint32_t                                    y,
+    uint32_t                                    z);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    buffer,
+    VkDeviceSize                                offset);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    srcBuffer,
+    VkBuffer                                    dstBuffer,
+    uint32_t                                    regionCount,
+    const VkBufferCopy*                         pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     dstImage,
+    VkImageLayout                               dstImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageCopy*                          pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     dstImage,
+    VkImageLayout                               dstImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageBlit*                          pRegions,
+    VkFilter                                    filter);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    srcBuffer,
+    VkImage                                     dstImage,
+    VkImageLayout                               dstImageLayout,
+    uint32_t                                    regionCount,
+    const VkBufferImageCopy*                    pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkBuffer                                    dstBuffer,
+    uint32_t                                    regionCount,
+    const VkBufferImageCopy*                    pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    dstBuffer,
+    VkDeviceSize                                dstOffset,
+    VkDeviceSize                                dataSize,
+    const uint32_t*                             pData);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(
+    VkCommandBuffer                             commandBuffer,
+    VkBuffer                                    dstBuffer,
+    VkDeviceSize                                dstOffset,
+    VkDeviceSize                                size,
+    uint32_t                                    data);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     image,
+    VkImageLayout                               imageLayout,
+    const VkClearColorValue*                    pColor,
+    uint32_t                                    rangeCount,
+    const VkImageSubresourceRange*              pRanges);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     image,
+    VkImageLayout                               imageLayout,
+    const VkClearDepthStencilValue*             pDepthStencil,
+    uint32_t                                    rangeCount,
+    const VkImageSubresourceRange*              pRanges);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    attachmentCount,
+    const VkClearAttachment*                    pAttachments,
+    uint32_t                                    rectCount,
+    const VkClearRect*                          pRects);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(
+    VkCommandBuffer                             commandBuffer,
+    VkImage                                     srcImage,
+    VkImageLayout                               srcImageLayout,
+    VkImage                                     dstImage,
+    VkImageLayout                               dstImageLayout,
+    uint32_t                                    regionCount,
+    const VkImageResolve*                       pRegions);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent(
+    VkCommandBuffer                             commandBuffer,
+    VkEvent                                     event,
+    VkPipelineStageFlags                        stageMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent(
+    VkCommandBuffer                             commandBuffer,
+    VkEvent                                     event,
+    VkPipelineStageFlags                        stageMask);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWaitEvents(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    eventCount,
+    const VkEvent*                              pEvents,
+    VkPipelineStageFlags                        srcStageMask,
+    VkPipelineStageFlags                        dstStageMask,
+    uint32_t                                    memoryBarrierCount,
+    const VkMemoryBarrier*                      pMemoryBarriers,
+    uint32_t                                    bufferMemoryBarrierCount,
+    const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
+    uint32_t                                    imageMemoryBarrierCount,
+    const VkImageMemoryBarrier*                 pImageMemoryBarriers);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(
+    VkCommandBuffer                             commandBuffer,
+    VkPipelineStageFlags                        srcStageMask,
+    VkPipelineStageFlags                        dstStageMask,
+    VkDependencyFlags                           dependencyFlags,
+    uint32_t                                    memoryBarrierCount,
+    const VkMemoryBarrier*                      pMemoryBarriers,
+    uint32_t                                    bufferMemoryBarrierCount,
+    const VkBufferMemoryBarrier*                pBufferMemoryBarriers,
+    uint32_t                                    imageMemoryBarrierCount,
+    const VkImageMemoryBarrier*                 pImageMemoryBarriers);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery(
+    VkCommandBuffer                             commandBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    query,
+    VkQueryControlFlags                         flags);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(
+    VkCommandBuffer                             commandBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    query);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool(
+    VkCommandBuffer                             commandBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    firstQuery,
+    uint32_t                                    queryCount);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(
+    VkCommandBuffer                             commandBuffer,
+    VkPipelineStageFlagBits                     pipelineStage,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    query);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults(
+    VkCommandBuffer                             commandBuffer,
+    VkQueryPool                                 queryPool,
+    uint32_t                                    firstQuery,
+    uint32_t                                    queryCount,
+    VkBuffer                                    dstBuffer,
+    VkDeviceSize                                dstOffset,
+    VkDeviceSize                                stride,
+    VkQueryResultFlags                          flags);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(
+    VkCommandBuffer                             commandBuffer,
+    VkPipelineLayout                            layout,
+    VkShaderStageFlags                          stageFlags,
+    uint32_t                                    offset,
+    uint32_t                                    size,
+    const void*                                 pValues);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdBeginRenderPass(
+    VkCommandBuffer                             commandBuffer,
+    const VkRenderPassBeginInfo*                pRenderPassBegin,
+    VkSubpassContents                           contents);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(
+    VkCommandBuffer                             commandBuffer,
+    VkSubpassContents                           contents);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(
+    VkCommandBuffer                             commandBuffer);
+
+VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(
+    VkCommandBuffer                             commandBuffer,
+    uint32_t                                    commandBufferCount,
+    const VkCommandBuffer*                      pCommandBuffers);
+#endif
+
+#define VK_KHR_surface 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
+
+#define VK_KHR_SURFACE_SPEC_VERSION       25
+#define VK_KHR_SURFACE_EXTENSION_NAME     "VK_KHR_surface"
+
+
+typedef enum VkColorSpaceKHR {
+    VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0,
+    VK_COLORSPACE_BEGIN_RANGE = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
+    VK_COLORSPACE_END_RANGE = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
+    VK_COLORSPACE_RANGE_SIZE = (VK_COLORSPACE_SRGB_NONLINEAR_KHR - VK_COLORSPACE_SRGB_NONLINEAR_KHR + 1),
+    VK_COLORSPACE_MAX_ENUM = 0x7FFFFFFF
+} VkColorSpaceKHR;
+
+typedef enum VkPresentModeKHR {
+    VK_PRESENT_MODE_IMMEDIATE_KHR = 0,
+    VK_PRESENT_MODE_MAILBOX_KHR = 1,
+    VK_PRESENT_MODE_FIFO_KHR = 2,
+    VK_PRESENT_MODE_FIFO_RELAXED_KHR = 3,
+    VK_PRESENT_MODE_BEGIN_RANGE = VK_PRESENT_MODE_IMMEDIATE_KHR,
+    VK_PRESENT_MODE_END_RANGE = VK_PRESENT_MODE_FIFO_RELAXED_KHR,
+    VK_PRESENT_MODE_RANGE_SIZE = (VK_PRESENT_MODE_FIFO_RELAXED_KHR - VK_PRESENT_MODE_IMMEDIATE_KHR + 1),
+    VK_PRESENT_MODE_MAX_ENUM = 0x7FFFFFFF
+} VkPresentModeKHR;
+
+
+typedef enum VkSurfaceTransformFlagBitsKHR {
+    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR = 0x00000001,
+    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR = 0x00000002,
+    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR = 0x00000004,
+    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR = 0x00000008,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR = 0x00000010,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR = 0x00000020,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR = 0x00000040,
+    VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR = 0x00000080,
+    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR = 0x00000100,
+} VkSurfaceTransformFlagBitsKHR;
+typedef VkFlags VkSurfaceTransformFlagsKHR;
+
+typedef enum VkCompositeAlphaFlagBitsKHR {
+    VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
+    VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR = 0x00000002,
+    VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR = 0x00000004,
+    VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR = 0x00000008,
+} VkCompositeAlphaFlagBitsKHR;
+typedef VkFlags VkCompositeAlphaFlagsKHR;
+
+typedef struct VkSurfaceCapabilitiesKHR {
+    uint32_t                         minImageCount;
+    uint32_t                         maxImageCount;
+    VkExtent2D                       currentExtent;
+    VkExtent2D                       minImageExtent;
+    VkExtent2D                       maxImageExtent;
+    uint32_t                         maxImageArrayLayers;
+    VkSurfaceTransformFlagsKHR       supportedTransforms;
+    VkSurfaceTransformFlagBitsKHR    currentTransform;
+    VkCompositeAlphaFlagsKHR         supportedCompositeAlpha;
+    VkImageUsageFlags                supportedUsageFlags;
+} VkSurfaceCapabilitiesKHR;
+
+typedef struct VkSurfaceFormatKHR {
+    VkFormat           format;
+    VkColorSpaceKHR    colorSpace;
+} VkSurfaceFormatKHR;
+
+
+typedef void (VKAPI_PTR *PFN_vkDestroySurfaceKHR)(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfaceFormatsKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModesKHR)(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(
+    VkInstance                                  instance,
+    VkSurfaceKHR                                surface,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    VkSurfaceKHR                                surface,
+    VkBool32*                                   pSupported);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkSurfaceKHR                                surface,
+    VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfaceFormatsKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkSurfaceKHR                                surface,
+    uint32_t*                                   pSurfaceFormatCount,
+    VkSurfaceFormatKHR*                         pSurfaceFormats);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkSurfaceKHR                                surface,
+    uint32_t*                                   pPresentModeCount,
+    VkPresentModeKHR*                           pPresentModes);
+#endif
+
+#define VK_KHR_swapchain 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSwapchainKHR)
+
+#define VK_KHR_SWAPCHAIN_SPEC_VERSION     67
+#define VK_KHR_SWAPCHAIN_EXTENSION_NAME   "VK_KHR_swapchain"
+
+typedef VkFlags VkSwapchainCreateFlagsKHR;
+
+typedef struct VkSwapchainCreateInfoKHR {
+    VkStructureType                  sType;
+    const void*                      pNext;
+    VkSwapchainCreateFlagsKHR        flags;
+    VkSurfaceKHR                     surface;
+    uint32_t                         minImageCount;
+    VkFormat                         imageFormat;
+    VkColorSpaceKHR                  imageColorSpace;
+    VkExtent2D                       imageExtent;
+    uint32_t                         imageArrayLayers;
+    VkImageUsageFlags                imageUsage;
+    VkSharingMode                    imageSharingMode;
+    uint32_t                         queueFamilyIndexCount;
+    const uint32_t*                  pQueueFamilyIndices;
+    VkSurfaceTransformFlagBitsKHR    preTransform;
+    VkCompositeAlphaFlagBitsKHR      compositeAlpha;
+    VkPresentModeKHR                 presentMode;
+    VkBool32                         clipped;
+    VkSwapchainKHR                   oldSwapchain;
+} VkSwapchainCreateInfoKHR;
+
+typedef struct VkPresentInfoKHR {
+    VkStructureType          sType;
+    const void*              pNext;
+    uint32_t                 waitSemaphoreCount;
+    const VkSemaphore*       pWaitSemaphores;
+    uint32_t                 swapchainCount;
+    const VkSwapchainKHR*    pSwapchains;
+    const uint32_t*          pImageIndices;
+    VkResult*                pResults;
+} VkPresentInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSwapchainKHR)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain);
+typedef void (VKAPI_PTR *PFN_vkDestroySwapchainKHR)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator);
+typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainImagesKHR)(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages);
+typedef VkResult (VKAPI_PTR *PFN_vkAcquireNextImageKHR)(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex);
+typedef VkResult (VKAPI_PTR *PFN_vkQueuePresentKHR)(VkQueue queue, const VkPresentInfoKHR* pPresentInfo);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSwapchainKHR(
+    VkDevice                                    device,
+    const VkSwapchainCreateInfoKHR*             pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSwapchainKHR*                             pSwapchain);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroySwapchainKHR(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainImagesKHR(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain,
+    uint32_t*                                   pSwapchainImageCount,
+    VkImage*                                    pSwapchainImages);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkAcquireNextImageKHR(
+    VkDevice                                    device,
+    VkSwapchainKHR                              swapchain,
+    uint64_t                                    timeout,
+    VkSemaphore                                 semaphore,
+    VkFence                                     fence,
+    uint32_t*                                   pImageIndex);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkQueuePresentKHR(
+    VkQueue                                     queue,
+    const VkPresentInfoKHR*                     pPresentInfo);
+#endif
+
+#define VK_KHR_display 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayKHR)
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDisplayModeKHR)
+
+#define VK_KHR_DISPLAY_SPEC_VERSION       21
+#define VK_KHR_DISPLAY_EXTENSION_NAME     "VK_KHR_display"
+
+
+typedef enum VkDisplayPlaneAlphaFlagBitsKHR {
+    VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR = 0x00000001,
+    VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR = 0x00000002,
+    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR = 0x00000004,
+    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR = 0x00000008,
+} VkDisplayPlaneAlphaFlagBitsKHR;
+typedef VkFlags VkDisplayModeCreateFlagsKHR;
+typedef VkFlags VkDisplayPlaneAlphaFlagsKHR;
+typedef VkFlags VkDisplaySurfaceCreateFlagsKHR;
+
+typedef struct VkDisplayPropertiesKHR {
+    VkDisplayKHR                  display;
+    const char*                   displayName;
+    VkExtent2D                    physicalDimensions;
+    VkExtent2D                    physicalResolution;
+    VkSurfaceTransformFlagsKHR    supportedTransforms;
+    VkBool32                      planeReorderPossible;
+    VkBool32                      persistentContent;
+} VkDisplayPropertiesKHR;
+
+typedef struct VkDisplayModeParametersKHR {
+    VkExtent2D    visibleRegion;
+    uint32_t      refreshRate;
+} VkDisplayModeParametersKHR;
+
+typedef struct VkDisplayModePropertiesKHR {
+    VkDisplayModeKHR              displayMode;
+    VkDisplayModeParametersKHR    parameters;
+} VkDisplayModePropertiesKHR;
+
+typedef struct VkDisplayModeCreateInfoKHR {
+    VkStructureType                sType;
+    const void*                    pNext;
+    VkDisplayModeCreateFlagsKHR    flags;
+    VkDisplayModeParametersKHR     parameters;
+} VkDisplayModeCreateInfoKHR;
+
+typedef struct VkDisplayPlaneCapabilitiesKHR {
+    VkDisplayPlaneAlphaFlagsKHR    supportedAlpha;
+    VkOffset2D                     minSrcPosition;
+    VkOffset2D                     maxSrcPosition;
+    VkExtent2D                     minSrcExtent;
+    VkExtent2D                     maxSrcExtent;
+    VkOffset2D                     minDstPosition;
+    VkOffset2D                     maxDstPosition;
+    VkExtent2D                     minDstExtent;
+    VkExtent2D                     maxDstExtent;
+} VkDisplayPlaneCapabilitiesKHR;
+
+typedef struct VkDisplayPlanePropertiesKHR {
+    VkDisplayKHR    currentDisplay;
+    uint32_t        currentStackIndex;
+} VkDisplayPlanePropertiesKHR;
+
+typedef struct VkDisplaySurfaceCreateInfoKHR {
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkDisplaySurfaceCreateFlagsKHR    flags;
+    VkDisplayModeKHR                  displayMode;
+    uint32_t                          planeIndex;
+    uint32_t                          planeStackIndex;
+    VkSurfaceTransformFlagBitsKHR     transform;
+    float                             globalAlpha;
+    VkDisplayPlaneAlphaFlagBitsKHR    alphaMode;
+    VkExtent2D                        imageExtent;
+} VkDisplaySurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR)(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkDisplayPlanePropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneSupportedDisplaysKHR)(VkPhysicalDevice physicalDevice, uint32_t planeIndex, uint32_t* pDisplayCount, VkDisplayKHR* pDisplays);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayModePropertiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, uint32_t* pPropertyCount, VkDisplayModePropertiesKHR* pProperties);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayModeKHR)(VkPhysicalDevice physicalDevice, VkDisplayKHR display, const VkDisplayModeCreateInfoKHR*pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDisplayModeKHR* pMode);
+typedef VkResult (VKAPI_PTR *PFN_vkGetDisplayPlaneCapabilitiesKHR)(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, uint32_t planeIndex, VkDisplayPlaneCapabilitiesKHR* pCapabilities);
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDisplayPlaneSurfaceKHR)(VkInstance instance, const VkDisplaySurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPropertiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pPropertyCount,
+    VkDisplayPropertiesKHR*                     pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceDisplayPlanePropertiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t*                                   pPropertyCount,
+    VkDisplayPlanePropertiesKHR*                pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneSupportedDisplaysKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    planeIndex,
+    uint32_t*                                   pDisplayCount,
+    VkDisplayKHR*                               pDisplays);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayModePropertiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkDisplayKHR                                display,
+    uint32_t*                                   pPropertyCount,
+    VkDisplayModePropertiesKHR*                 pProperties);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayModeKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkDisplayKHR                                display,
+    const VkDisplayModeCreateInfoKHR*           pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDisplayModeKHR*                           pMode);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetDisplayPlaneCapabilitiesKHR(
+    VkPhysicalDevice                            physicalDevice,
+    VkDisplayModeKHR                            mode,
+    uint32_t                                    planeIndex,
+    VkDisplayPlaneCapabilitiesKHR*              pCapabilities);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDisplayPlaneSurfaceKHR(
+    VkInstance                                  instance,
+    const VkDisplaySurfaceCreateInfoKHR*        pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+#endif
+
+#define VK_KHR_display_swapchain 1
+#define VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION 9
+#define VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME "VK_KHR_display_swapchain"
+
+typedef struct VkDisplayPresentInfoKHR {
+    VkStructureType    sType;
+    const void*        pNext;
+    VkRect2D           srcRect;
+    VkRect2D           dstRect;
+    VkBool32           persistent;
+} VkDisplayPresentInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateSharedSwapchainsKHR)(VkDevice device, uint32_t swapchainCount, const VkSwapchainCreateInfoKHR* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchains);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateSharedSwapchainsKHR(
+    VkDevice                                    device,
+    uint32_t                                    swapchainCount,
+    const VkSwapchainCreateInfoKHR*             pCreateInfos,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSwapchainKHR*                             pSwapchains);
+#endif
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+#define VK_KHR_xlib_surface 1
+#include <X11/Xlib.h>
+
+#define VK_KHR_XLIB_SURFACE_SPEC_VERSION  6
+#define VK_KHR_XLIB_SURFACE_EXTENSION_NAME "VK_KHR_xlib_surface"
+
+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
+
+typedef struct VkXlibSurfaceCreateInfoKHR {
+    VkStructureType                sType;
+    const void*                    pNext;
+    VkXlibSurfaceCreateFlagsKHR    flags;
+    Display*                       dpy;
+    Window                         window;
+} VkXlibSurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateXlibSurfaceKHR)(VkInstance instance, const VkXlibSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, Display* dpy, VisualID visualID);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXlibSurfaceKHR(
+    VkInstance                                  instance,
+    const VkXlibSurfaceCreateInfoKHR*           pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXlibPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    Display*                                    dpy,
+    VisualID                                    visualID);
+#endif
+#endif /* VK_USE_PLATFORM_XLIB_KHR */
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+#define VK_KHR_xcb_surface 1
+#include <xcb/xcb.h>
+
+#define VK_KHR_XCB_SURFACE_SPEC_VERSION   6
+#define VK_KHR_XCB_SURFACE_EXTENSION_NAME "VK_KHR_xcb_surface"
+
+typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
+
+typedef struct VkXcbSurfaceCreateInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkXcbSurfaceCreateFlagsKHR    flags;
+    xcb_connection_t*             connection;
+    xcb_window_t                  window;
+} VkXcbSurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateXcbSurfaceKHR)(VkInstance instance, const VkXcbSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, xcb_connection_t* connection, xcb_visualid_t visual_id);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateXcbSurfaceKHR(
+    VkInstance                                  instance,
+    const VkXcbSurfaceCreateInfoKHR*            pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceXcbPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    xcb_connection_t*                           connection,
+    xcb_visualid_t                              visual_id);
+#endif
+#endif /* VK_USE_PLATFORM_XCB_KHR */
+
+#ifdef VK_USE_PLATFORM_WAYLAND_KHR
+#define VK_KHR_wayland_surface 1
+#include <wayland-client.h>
+
+#define VK_KHR_WAYLAND_SURFACE_SPEC_VERSION 5
+#define VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME "VK_KHR_wayland_surface"
+
+typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
+
+typedef struct VkWaylandSurfaceCreateInfoKHR {
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkWaylandSurfaceCreateFlagsKHR    flags;
+    struct wl_display*                display;
+    struct wl_surface*                surface;
+} VkWaylandSurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateWaylandSurfaceKHR)(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, struct wl_display* display);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateWaylandSurfaceKHR(
+    VkInstance                                  instance,
+    const VkWaylandSurfaceCreateInfoKHR*        pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWaylandPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    struct wl_display*                          display);
+#endif
+#endif /* VK_USE_PLATFORM_WAYLAND_KHR */
+
+#ifdef VK_USE_PLATFORM_MIR_KHR
+#define VK_KHR_mir_surface 1
+#include <mir_toolkit/client_types.h>
+
+#define VK_KHR_MIR_SURFACE_SPEC_VERSION   4
+#define VK_KHR_MIR_SURFACE_EXTENSION_NAME "VK_KHR_mir_surface"
+
+typedef VkFlags VkMirSurfaceCreateFlagsKHR;
+
+typedef struct VkMirSurfaceCreateInfoKHR {
+    VkStructureType               sType;
+    const void*                   pNext;
+    VkMirSurfaceCreateFlagsKHR    flags;
+    MirConnection*                connection;
+    MirSurface*                   mirSurface;
+} VkMirSurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateMirSurfaceKHR)(VkInstance instance, const VkMirSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, MirConnection* connection);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateMirSurfaceKHR(
+    VkInstance                                  instance,
+    const VkMirSurfaceCreateInfoKHR*            pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceMirPresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex,
+    MirConnection*                              connection);
+#endif
+#endif /* VK_USE_PLATFORM_MIR_KHR */
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+#define VK_KHR_android_surface 1
+#include <android/native_window.h>
+
+#define VK_KHR_ANDROID_SURFACE_SPEC_VERSION 6
+#define VK_KHR_ANDROID_SURFACE_EXTENSION_NAME "VK_KHR_android_surface"
+
+typedef VkFlags VkAndroidSurfaceCreateFlagsKHR;
+
+typedef struct VkAndroidSurfaceCreateInfoKHR {
+    VkStructureType                   sType;
+    const void*                       pNext;
+    VkAndroidSurfaceCreateFlagsKHR    flags;
+    ANativeWindow*                    window;
+} VkAndroidSurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateAndroidSurfaceKHR)(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateAndroidSurfaceKHR(
+    VkInstance                                  instance,
+    const VkAndroidSurfaceCreateInfoKHR*        pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+#endif
+#endif /* VK_USE_PLATFORM_ANDROID_KHR */
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+#define VK_KHR_win32_surface 1
+#include <windows.h>
+
+#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 5
+#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface"
+
+typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
+
+typedef struct VkWin32SurfaceCreateInfoKHR {
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkWin32SurfaceCreateFlagsKHR    flags;
+    HINSTANCE                       hinstance;
+    HWND                            hwnd;
+} VkWin32SurfaceCreateInfoKHR;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
+typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
+    VkInstance                                  instance,
+    const VkWin32SurfaceCreateInfoKHR*          pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkSurfaceKHR*                               pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
+    VkPhysicalDevice                            physicalDevice,
+    uint32_t                                    queueFamilyIndex);
+#endif
+#endif /* VK_USE_PLATFORM_WIN32_KHR */
+
+#define VK_EXT_debug_report 1
+VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkDebugReportCallbackEXT)
+
+#define VK_EXT_DEBUG_REPORT_SPEC_VERSION  1
+#define VK_EXT_DEBUG_REPORT_EXTENSION_NAME "VK_EXT_debug_report"
+
+
+typedef enum VkDebugReportObjectTypeEXT {
+    VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT = 0,
+    VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT = 1,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT = 2,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT = 3,
+    VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT = 4,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT = 5,
+    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT = 6,
+    VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT = 7,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT = 8,
+    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT = 9,
+    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT = 10,
+    VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT = 11,
+    VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT = 12,
+    VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT = 13,
+    VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT = 14,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT = 15,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT = 16,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT = 17,
+    VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT = 18,
+    VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT = 19,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT = 20,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT = 21,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT = 22,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT = 23,
+    VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT = 24,
+    VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT = 25,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT = 26,
+    VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT = 27,
+    VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT = 28,
+} VkDebugReportObjectTypeEXT;
+
+typedef enum VkDebugReportErrorEXT {
+    VK_DEBUG_REPORT_ERROR_NONE_EXT = 0,
+    VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT = 1,
+} VkDebugReportErrorEXT;
+
+
+typedef enum VkDebugReportFlagBitsEXT {
+    VK_DEBUG_REPORT_INFORMATION_BIT_EXT = 0x00000001,
+    VK_DEBUG_REPORT_WARNING_BIT_EXT = 0x00000002,
+    VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT = 0x00000004,
+    VK_DEBUG_REPORT_ERROR_BIT_EXT = 0x00000008,
+    VK_DEBUG_REPORT_DEBUG_BIT_EXT = 0x00000010,
+} VkDebugReportFlagBitsEXT;
+typedef VkFlags VkDebugReportFlagsEXT;
+
+typedef VkBool32 (VKAPI_PTR *PFN_vkDebugReportCallbackEXT)(
+    VkDebugReportFlagsEXT                       flags,
+    VkDebugReportObjectTypeEXT                  objectType,
+    uint64_t                                    object,
+    size_t                                      location,
+    int32_t                                     messageCode,
+    const char*                                 pLayerPrefix,
+    const char*                                 pMessage,
+    void*                                       pUserData);
+
+
+typedef struct VkDebugReportCallbackCreateInfoEXT {
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkDebugReportFlagsEXT           flags;
+    PFN_vkDebugReportCallbackEXT    pfnCallback;
+    void*                           pUserData;
+} VkDebugReportCallbackCreateInfoEXT;
+
+
+typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugReportCallbackEXT)(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+typedef void (VKAPI_PTR *PFN_vkDestroyDebugReportCallbackEXT)(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+typedef void (VKAPI_PTR *PFN_vkDebugReportMessageEXT)(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
+    VkInstance                                  instance,
+    const VkDebugReportCallbackCreateInfoEXT*   pCreateInfo,
+    const VkAllocationCallbacks*                pAllocator,
+    VkDebugReportCallbackEXT*                   pCallback);
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(
+    VkInstance                                  instance,
+    VkDebugReportCallbackEXT                    callback,
+    const VkAllocationCallbacks*                pAllocator);
+
+VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
+    VkInstance                                  instance,
+    VkDebugReportFlagsEXT                       flags,
+    VkDebugReportObjectTypeEXT                  objectType,
+    uint64_t                                    object,
+    size_t                                      location,
+    int32_t                                     messageCode,
+    const char*                                 pLayerPrefix,
+    const char*                                 pMessage);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vulkan/include/vulkan/vulkan_loader_data.h b/vulkan/include/vulkan/vulkan_loader_data.h
new file mode 100644
index 0000000..968a7aa
--- /dev/null
+++ b/vulkan/include/vulkan/vulkan_loader_data.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef VULKAN_VULKAN_LOADER_DATA_H
+#define VULKAN_VULKAN_LOADER_DATA_H
+
+#include <string>
+
+namespace vulkan {
+    struct LoaderData {
+        std::string layer_path;
+        __attribute__((visibility("default"))) static LoaderData& GetInstance();
+    };
+}
+
+#endif
diff --git a/vulkan/libvulkan/Android.mk b/vulkan/libvulkan/Android.mk
new file mode 100644
index 0000000..71788a9
--- /dev/null
+++ b/vulkan/libvulkan/Android.mk
@@ -0,0 +1,55 @@
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+LOCAL_SANITIZE := integer
+
+LOCAL_CFLAGS := -DLOG_TAG=\"vulkan\" \
+	-DVK_USE_PLATFORM_ANDROID_KHR \
+	-std=c99 -fvisibility=hidden -fstrict-aliasing \
+	-Weverything -Werror \
+	-Wno-padded \
+	-Wno-switch-enum \
+	-Wno-undef
+#LOCAL_CFLAGS += -DLOG_NDEBUG=0
+LOCAL_CPPFLAGS := -std=c++14 \
+	-Wno-c99-extensions \
+	-Wno-c++98-compat-pedantic \
+	-Wno-exit-time-destructors \
+	-Wno-global-constructors \
+	-Wno-zero-length-array
+
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include \
+	system/core/libsync/include
+
+LOCAL_SRC_FILES := \
+	api.cpp \
+	api_gen.cpp \
+	debug_report.cpp \
+	driver.cpp \
+	driver_gen.cpp \
+	layers_extensions.cpp \
+	stubhal.cpp \
+	swapchain.cpp \
+	vulkan_loader_data.cpp
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_SHARED_LIBRARIES := libhardware liblog libsync libutils libcutils
+
+LOCAL_MODULE := libvulkan
+include $(BUILD_SHARED_LIBRARY)
diff --git a/vulkan/libvulkan/api.cpp b/vulkan/libvulkan/api.cpp
new file mode 100644
index 0000000..28b172d
--- /dev/null
+++ b/vulkan/libvulkan/api.cpp
@@ -0,0 +1,1268 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// The API layer of the loader defines Vulkan API and manages layers.  The
+// entrypoints are generated and defined in api_dispatch.cpp.  Most of them
+// simply find the dispatch table and jump.
+//
+// There are a few of them requiring manual code for things such as layer
+// discovery or chaining.  They call into functions defined in this file.
+
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <mutex>
+#include <new>
+#include <utility>
+#include <cutils/properties.h>
+#include <log/log.h>
+
+#include <vulkan/vk_layer_interface.h>
+#include "api.h"
+#include "driver.h"
+#include "layers_extensions.h"
+
+namespace vulkan {
+namespace api {
+
+namespace {
+
+// Provide overridden layer names when there are implicit layers.  No effect
+// otherwise.
+class OverrideLayerNames {
+   public:
+    OverrideLayerNames(bool is_instance, const VkAllocationCallbacks& allocator)
+        : is_instance_(is_instance),
+          allocator_(allocator),
+          scope_(VK_SYSTEM_ALLOCATION_SCOPE_COMMAND),
+          names_(nullptr),
+          name_count_(0),
+          implicit_layers_() {
+        implicit_layers_.result = VK_SUCCESS;
+    }
+
+    ~OverrideLayerNames() {
+        allocator_.pfnFree(allocator_.pUserData, names_);
+        allocator_.pfnFree(allocator_.pUserData, implicit_layers_.elements);
+        allocator_.pfnFree(allocator_.pUserData, implicit_layers_.name_pool);
+    }
+
+    VkResult Parse(const char* const* names, uint32_t count) {
+        AddImplicitLayers();
+
+        const auto& arr = implicit_layers_;
+        if (arr.result != VK_SUCCESS)
+            return arr.result;
+
+        // no need to override when there is no implicit layer
+        if (!arr.count)
+            return VK_SUCCESS;
+
+        names_ = AllocateNameArray(arr.count + count);
+        if (!names_)
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+        // add implicit layer names
+        for (uint32_t i = 0; i < arr.count; i++)
+            names_[i] = GetImplicitLayerName(i);
+
+        name_count_ = arr.count;
+
+        // add explicit layer names
+        for (uint32_t i = 0; i < count; i++) {
+            // ignore explicit layers that are also implicit
+            if (IsImplicitLayer(names[i]))
+                continue;
+
+            names_[name_count_++] = names[i];
+        }
+
+        return VK_SUCCESS;
+    }
+
+    const char* const* Names() const { return names_; }
+
+    uint32_t Count() const { return name_count_; }
+
+   private:
+    struct ImplicitLayer {
+        int priority;
+        size_t name_offset;
+    };
+
+    struct ImplicitLayerArray {
+        ImplicitLayer* elements;
+        uint32_t max_count;
+        uint32_t count;
+
+        char* name_pool;
+        size_t max_pool_size;
+        size_t pool_size;
+
+        VkResult result;
+    };
+
+    void AddImplicitLayers() {
+        if (!is_instance_ || !driver::Debuggable())
+            return;
+
+        ParseDebugVulkanLayers();
+        property_list(ParseDebugVulkanLayer, this);
+
+        // sort by priorities
+        auto& arr = implicit_layers_;
+        std::sort(arr.elements, arr.elements + arr.count,
+                  [](const ImplicitLayer& a, const ImplicitLayer& b) {
+                      return (a.priority < b.priority);
+                  });
+    }
+
+    void ParseDebugVulkanLayers() {
+        // debug.vulkan.layers specifies colon-separated layer names
+        char prop[PROPERTY_VALUE_MAX];
+        if (!property_get("debug.vulkan.layers", prop, ""))
+            return;
+
+        // assign negative/high priorities to them
+        int prio = -PROPERTY_VALUE_MAX;
+
+        const char* p = prop;
+        const char* delim;
+        while ((delim = strchr(p, ':'))) {
+            if (delim > p)
+                AddImplicitLayer(prio, p, static_cast<size_t>(delim - p));
+
+            prio++;
+            p = delim + 1;
+        }
+
+        if (p[0] != '\0')
+            AddImplicitLayer(prio, p, strlen(p));
+    }
+
+    static void ParseDebugVulkanLayer(const char* key,
+                                      const char* val,
+                                      void* user_data) {
+        static const char prefix[] = "debug.vulkan.layer.";
+        const size_t prefix_len = sizeof(prefix) - 1;
+
+        if (strncmp(key, prefix, prefix_len) || val[0] == '\0')
+            return;
+        key += prefix_len;
+
+        // debug.vulkan.layer.<priority>
+        int priority = -1;
+        if (key[0] >= '0' && key[0] <= '9')
+            priority = atoi(key);
+
+        if (priority < 0) {
+            ALOGW("Ignored implicit layer %s with invalid priority %s", val,
+                  key);
+            return;
+        }
+
+        OverrideLayerNames& override_layers =
+            *reinterpret_cast<OverrideLayerNames*>(user_data);
+        override_layers.AddImplicitLayer(priority, val, strlen(val));
+    }
+
+    void AddImplicitLayer(int priority, const char* name, size_t len) {
+        if (!GrowImplicitLayerArray(1, 0))
+            return;
+
+        auto& arr = implicit_layers_;
+        auto& layer = arr.elements[arr.count++];
+
+        layer.priority = priority;
+        layer.name_offset = AddImplicitLayerName(name, len);
+
+        ALOGV("Added implicit layer %s", GetImplicitLayerName(arr.count - 1));
+    }
+
+    size_t AddImplicitLayerName(const char* name, size_t len) {
+        if (!GrowImplicitLayerArray(0, len + 1))
+            return 0;
+
+        // add the name to the pool
+        auto& arr = implicit_layers_;
+        size_t offset = arr.pool_size;
+        char* dst = arr.name_pool + offset;
+
+        std::copy(name, name + len, dst);
+        dst[len] = '\0';
+
+        arr.pool_size += len + 1;
+
+        return offset;
+    }
+
+    bool GrowImplicitLayerArray(uint32_t layer_count, size_t name_size) {
+        const uint32_t initial_max_count = 16;
+        const size_t initial_max_pool_size = 512;
+
+        auto& arr = implicit_layers_;
+
+        // grow the element array if needed
+        while (arr.count + layer_count > arr.max_count) {
+            uint32_t new_max_count =
+                (arr.max_count) ? (arr.max_count << 1) : initial_max_count;
+            void* new_mem = nullptr;
+
+            if (new_max_count > arr.max_count) {
+                new_mem = allocator_.pfnReallocation(
+                    allocator_.pUserData, arr.elements,
+                    sizeof(ImplicitLayer) * new_max_count,
+                    alignof(ImplicitLayer), scope_);
+            }
+
+            if (!new_mem) {
+                arr.result = VK_ERROR_OUT_OF_HOST_MEMORY;
+                arr.count = 0;
+                return false;
+            }
+
+            arr.elements = reinterpret_cast<ImplicitLayer*>(new_mem);
+            arr.max_count = new_max_count;
+        }
+
+        // grow the name pool if needed
+        while (arr.pool_size + name_size > arr.max_pool_size) {
+            size_t new_max_pool_size = (arr.max_pool_size)
+                                           ? (arr.max_pool_size << 1)
+                                           : initial_max_pool_size;
+            void* new_mem = nullptr;
+
+            if (new_max_pool_size > arr.max_pool_size) {
+                new_mem = allocator_.pfnReallocation(
+                    allocator_.pUserData, arr.name_pool, new_max_pool_size,
+                    alignof(char), scope_);
+            }
+
+            if (!new_mem) {
+                arr.result = VK_ERROR_OUT_OF_HOST_MEMORY;
+                arr.pool_size = 0;
+                return false;
+            }
+
+            arr.name_pool = reinterpret_cast<char*>(new_mem);
+            arr.max_pool_size = new_max_pool_size;
+        }
+
+        return true;
+    }
+
+    const char* GetImplicitLayerName(uint32_t index) const {
+        const auto& arr = implicit_layers_;
+
+        // this may return nullptr when arr.result is not VK_SUCCESS
+        return implicit_layers_.name_pool + arr.elements[index].name_offset;
+    }
+
+    bool IsImplicitLayer(const char* name) const {
+        const auto& arr = implicit_layers_;
+
+        for (uint32_t i = 0; i < arr.count; i++) {
+            if (strcmp(name, GetImplicitLayerName(i)) == 0)
+                return true;
+        }
+
+        return false;
+    }
+
+    const char** AllocateNameArray(uint32_t count) const {
+        return reinterpret_cast<const char**>(allocator_.pfnAllocation(
+            allocator_.pUserData, sizeof(const char*) * count,
+            alignof(const char*), scope_));
+    }
+
+    const bool is_instance_;
+    const VkAllocationCallbacks& allocator_;
+    const VkSystemAllocationScope scope_;
+
+    const char** names_;
+    uint32_t name_count_;
+
+    ImplicitLayerArray implicit_layers_;
+};
+
+// Provide overridden extension names when there are implicit extensions.
+// No effect otherwise.
+//
+// This is used only to enable VK_EXT_debug_report.
+class OverrideExtensionNames {
+   public:
+    OverrideExtensionNames(bool is_instance,
+                           const VkAllocationCallbacks& allocator)
+        : is_instance_(is_instance),
+          allocator_(allocator),
+          scope_(VK_SYSTEM_ALLOCATION_SCOPE_COMMAND),
+          names_(nullptr),
+          name_count_(0),
+          install_debug_callback_(false) {}
+
+    ~OverrideExtensionNames() {
+        allocator_.pfnFree(allocator_.pUserData, names_);
+    }
+
+    VkResult Parse(const char* const* names, uint32_t count) {
+        // this is only for debug.vulkan.enable_callback
+        if (!EnableDebugCallback())
+            return VK_SUCCESS;
+
+        names_ = AllocateNameArray(count + 1);
+        if (!names_)
+            return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+        std::copy(names, names + count, names_);
+
+        name_count_ = count;
+        names_[name_count_++] = "VK_EXT_debug_report";
+
+        install_debug_callback_ = true;
+
+        return VK_SUCCESS;
+    }
+
+    const char* const* Names() const { return names_; }
+
+    uint32_t Count() const { return name_count_; }
+
+    bool InstallDebugCallback() const { return install_debug_callback_; }
+
+   private:
+    bool EnableDebugCallback() const {
+        return (is_instance_ && driver::Debuggable() &&
+                property_get_bool("debug.vulkan.enable_callback", false));
+    }
+
+    const char** AllocateNameArray(uint32_t count) const {
+        return reinterpret_cast<const char**>(allocator_.pfnAllocation(
+            allocator_.pUserData, sizeof(const char*) * count,
+            alignof(const char*), scope_));
+    }
+
+    const bool is_instance_;
+    const VkAllocationCallbacks& allocator_;
+    const VkSystemAllocationScope scope_;
+
+    const char** names_;
+    uint32_t name_count_;
+    bool install_debug_callback_;
+};
+
+// vkCreateInstance and vkCreateDevice helpers with support for layer
+// chaining.
+class LayerChain {
+   public:
+    struct ActiveLayer {
+        LayerRef ref;
+        union {
+            VkLayerInstanceLink instance_link;
+            VkLayerDeviceLink device_link;
+        };
+    };
+
+    static VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+                                   const VkAllocationCallbacks* allocator,
+                                   VkInstance* instance_out);
+
+    static VkResult CreateDevice(VkPhysicalDevice physical_dev,
+                                 const VkDeviceCreateInfo* create_info,
+                                 const VkAllocationCallbacks* allocator,
+                                 VkDevice* dev_out);
+
+    static void DestroyInstance(VkInstance instance,
+                                const VkAllocationCallbacks* allocator);
+
+    static void DestroyDevice(VkDevice dev,
+                              const VkAllocationCallbacks* allocator);
+
+    static const ActiveLayer* GetActiveLayers(VkPhysicalDevice physical_dev,
+                                              uint32_t& count);
+
+   private:
+    LayerChain(bool is_instance, const VkAllocationCallbacks& allocator);
+    ~LayerChain();
+
+    VkResult ActivateLayers(const char* const* layer_names,
+                            uint32_t layer_count,
+                            const char* const* extension_names,
+                            uint32_t extension_count);
+    VkResult ActivateLayers(VkPhysicalDevice physical_dev,
+                            const char* const* layer_names,
+                            uint32_t layer_count,
+                            const char* const* extension_names,
+                            uint32_t extension_count);
+    ActiveLayer* AllocateLayerArray(uint32_t count) const;
+    VkResult LoadLayer(ActiveLayer& layer, const char* name);
+    void SetupLayerLinks();
+
+    bool Empty() const;
+    void ModifyCreateInfo(VkInstanceCreateInfo& info);
+    void ModifyCreateInfo(VkDeviceCreateInfo& info);
+
+    VkResult Create(const VkInstanceCreateInfo* create_info,
+                    const VkAllocationCallbacks* allocator,
+                    VkInstance* instance_out);
+
+    VkResult Create(VkPhysicalDevice physical_dev,
+                    const VkDeviceCreateInfo* create_info,
+                    const VkAllocationCallbacks* allocator,
+                    VkDevice* dev_out);
+
+    VkResult ValidateExtensions(const char* const* extension_names,
+                                uint32_t extension_count);
+    VkResult ValidateExtensions(VkPhysicalDevice physical_dev,
+                                const char* const* extension_names,
+                                uint32_t extension_count);
+    VkExtensionProperties* AllocateDriverExtensionArray(uint32_t count) const;
+    bool IsLayerExtension(const char* name) const;
+    bool IsDriverExtension(const char* name) const;
+
+    template <typename DataType>
+    void StealLayers(DataType& data);
+
+    static void DestroyLayers(ActiveLayer* layers,
+                              uint32_t count,
+                              const VkAllocationCallbacks& allocator);
+
+    static VKAPI_ATTR VkResult SetInstanceLoaderData(VkInstance instance,
+                                                     void* object);
+    static VKAPI_ATTR VkResult SetDeviceLoaderData(VkDevice device,
+                                                   void* object);
+
+    static VKAPI_ATTR VkBool32
+    DebugReportCallback(VkDebugReportFlagsEXT flags,
+                        VkDebugReportObjectTypeEXT obj_type,
+                        uint64_t obj,
+                        size_t location,
+                        int32_t msg_code,
+                        const char* layer_prefix,
+                        const char* msg,
+                        void* user_data);
+
+    const bool is_instance_;
+    const VkAllocationCallbacks& allocator_;
+
+    OverrideLayerNames override_layers_;
+    OverrideExtensionNames override_extensions_;
+
+    ActiveLayer* layers_;
+    uint32_t layer_count_;
+
+    PFN_vkGetInstanceProcAddr get_instance_proc_addr_;
+    PFN_vkGetDeviceProcAddr get_device_proc_addr_;
+
+    union {
+        VkLayerInstanceCreateInfo instance_chain_info_[2];
+        VkLayerDeviceCreateInfo device_chain_info_[2];
+    };
+
+    VkExtensionProperties* driver_extensions_;
+    uint32_t driver_extension_count_;
+    std::bitset<driver::ProcHook::EXTENSION_COUNT> enabled_extensions_;
+};
+
+LayerChain::LayerChain(bool is_instance, const VkAllocationCallbacks& allocator)
+    : is_instance_(is_instance),
+      allocator_(allocator),
+      override_layers_(is_instance, allocator),
+      override_extensions_(is_instance, allocator),
+      layers_(nullptr),
+      layer_count_(0),
+      get_instance_proc_addr_(nullptr),
+      get_device_proc_addr_(nullptr),
+      driver_extensions_(nullptr),
+      driver_extension_count_(0) {
+    enabled_extensions_.set(driver::ProcHook::EXTENSION_CORE);
+}
+
+LayerChain::~LayerChain() {
+    allocator_.pfnFree(allocator_.pUserData, driver_extensions_);
+    DestroyLayers(layers_, layer_count_, allocator_);
+}
+
+VkResult LayerChain::ActivateLayers(const char* const* layer_names,
+                                    uint32_t layer_count,
+                                    const char* const* extension_names,
+                                    uint32_t extension_count) {
+    VkResult result = override_layers_.Parse(layer_names, layer_count);
+    if (result != VK_SUCCESS)
+        return result;
+
+    result = override_extensions_.Parse(extension_names, extension_count);
+    if (result != VK_SUCCESS)
+        return result;
+
+    if (override_layers_.Count()) {
+        layer_names = override_layers_.Names();
+        layer_count = override_layers_.Count();
+    }
+
+    if (!layer_count) {
+        // point head of chain to the driver
+        get_instance_proc_addr_ = driver::GetInstanceProcAddr;
+
+        return VK_SUCCESS;
+    }
+
+    layers_ = AllocateLayerArray(layer_count);
+    if (!layers_)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    // load layers
+    for (uint32_t i = 0; i < layer_count; i++) {
+        result = LoadLayer(layers_[i], layer_names[i]);
+        if (result != VK_SUCCESS)
+            return result;
+
+        // count loaded layers for proper destructions on errors
+        layer_count_++;
+    }
+
+    SetupLayerLinks();
+
+    return VK_SUCCESS;
+}
+
+VkResult LayerChain::ActivateLayers(VkPhysicalDevice physical_dev,
+                                    const char* const* layer_names,
+                                    uint32_t layer_count,
+                                    const char* const* extension_names,
+                                    uint32_t extension_count) {
+    uint32_t instance_layer_count;
+    const ActiveLayer* instance_layers =
+        GetActiveLayers(physical_dev, instance_layer_count);
+
+    // log a message if the application device layer array is not empty nor an
+    // exact match of the instance layer array.
+    if (layer_count) {
+        bool exact_match = (instance_layer_count == layer_count);
+        if (exact_match) {
+            for (uint32_t i = 0; i < instance_layer_count; i++) {
+                const Layer& l = *instance_layers[i].ref;
+                if (strcmp(GetLayerProperties(l).layerName, layer_names[i])) {
+                    exact_match = false;
+                    break;
+                }
+            }
+        }
+
+        if (!exact_match) {
+            ALOGW("Device layers");
+            for (uint32_t i = 0; i < layer_count; i++)
+                ALOGW("  %s", layer_names[i]);
+            ALOGW(
+                "disagree with instance layers and are overridden by "
+                "instance layers");
+        }
+    }
+
+    VkResult result =
+        override_extensions_.Parse(extension_names, extension_count);
+    if (result != VK_SUCCESS)
+        return result;
+
+    if (!instance_layer_count) {
+        // point head of chain to the driver
+        get_instance_proc_addr_ = driver::GetInstanceProcAddr;
+        get_device_proc_addr_ = driver::GetDeviceProcAddr;
+
+        return VK_SUCCESS;
+    }
+
+    layers_ = AllocateLayerArray(instance_layer_count);
+    if (!layers_)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    for (uint32_t i = 0; i < instance_layer_count; i++) {
+        const Layer& l = *instance_layers[i].ref;
+
+        // no need to and cannot chain non-global layers
+        if (!IsLayerGlobal(l))
+            continue;
+
+        // this never fails
+        new (&layers_[layer_count_++]) ActiveLayer{GetLayerRef(l), {}};
+    }
+
+    SetupLayerLinks();
+
+    return VK_SUCCESS;
+}
+
+LayerChain::ActiveLayer* LayerChain::AllocateLayerArray(uint32_t count) const {
+    VkSystemAllocationScope scope = (is_instance_)
+                                        ? VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
+                                        : VK_SYSTEM_ALLOCATION_SCOPE_COMMAND;
+
+    return reinterpret_cast<ActiveLayer*>(allocator_.pfnAllocation(
+        allocator_.pUserData, sizeof(ActiveLayer) * count, alignof(ActiveLayer),
+        scope));
+}
+
+VkResult LayerChain::LoadLayer(ActiveLayer& layer, const char* name) {
+    const Layer* l = FindLayer(name);
+    if (!l) {
+        ALOGW("Failed to find layer %s", name);
+        return VK_ERROR_LAYER_NOT_PRESENT;
+    }
+
+    new (&layer) ActiveLayer{GetLayerRef(*l), {}};
+    if (!layer.ref) {
+        ALOGW("Failed to open layer %s", name);
+        layer.ref.~LayerRef();
+        return VK_ERROR_LAYER_NOT_PRESENT;
+    }
+
+    ALOGI("Loaded layer %s", name);
+
+    return VK_SUCCESS;
+}
+
+void LayerChain::SetupLayerLinks() {
+    if (is_instance_) {
+        for (uint32_t i = 0; i < layer_count_; i++) {
+            ActiveLayer& layer = layers_[i];
+
+            // point head of chain to the first layer
+            if (i == 0)
+                get_instance_proc_addr_ = layer.ref.GetGetInstanceProcAddr();
+
+            // point tail of chain to the driver
+            if (i == layer_count_ - 1) {
+                layer.instance_link.pNext = nullptr;
+                layer.instance_link.pfnNextGetInstanceProcAddr =
+                    driver::GetInstanceProcAddr;
+                break;
+            }
+
+            const ActiveLayer& next = layers_[i + 1];
+
+            // const_cast as some naughty layers want to modify our links!
+            layer.instance_link.pNext =
+                const_cast<VkLayerInstanceLink*>(&next.instance_link);
+            layer.instance_link.pfnNextGetInstanceProcAddr =
+                next.ref.GetGetInstanceProcAddr();
+        }
+    } else {
+        for (uint32_t i = 0; i < layer_count_; i++) {
+            ActiveLayer& layer = layers_[i];
+
+            // point head of chain to the first layer
+            if (i == 0) {
+                get_instance_proc_addr_ = layer.ref.GetGetInstanceProcAddr();
+                get_device_proc_addr_ = layer.ref.GetGetDeviceProcAddr();
+            }
+
+            // point tail of chain to the driver
+            if (i == layer_count_ - 1) {
+                layer.device_link.pNext = nullptr;
+                layer.device_link.pfnNextGetInstanceProcAddr =
+                    driver::GetInstanceProcAddr;
+                layer.device_link.pfnNextGetDeviceProcAddr =
+                    driver::GetDeviceProcAddr;
+                break;
+            }
+
+            const ActiveLayer& next = layers_[i + 1];
+
+            // const_cast as some naughty layers want to modify our links!
+            layer.device_link.pNext =
+                const_cast<VkLayerDeviceLink*>(&next.device_link);
+            layer.device_link.pfnNextGetInstanceProcAddr =
+                next.ref.GetGetInstanceProcAddr();
+            layer.device_link.pfnNextGetDeviceProcAddr =
+                next.ref.GetGetDeviceProcAddr();
+        }
+    }
+}
+
+bool LayerChain::Empty() const {
+    return (!layer_count_ && !override_layers_.Count() &&
+            !override_extensions_.Count());
+}
+
+void LayerChain::ModifyCreateInfo(VkInstanceCreateInfo& info) {
+    if (layer_count_) {
+        auto& link_info = instance_chain_info_[1];
+        link_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+        link_info.pNext = info.pNext;
+        link_info.function = VK_LAYER_FUNCTION_LINK;
+        link_info.u.pLayerInfo = &layers_[0].instance_link;
+
+        auto& cb_info = instance_chain_info_[0];
+        cb_info.sType = VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO;
+        cb_info.pNext = &link_info;
+        cb_info.function = VK_LAYER_FUNCTION_DATA_CALLBACK;
+        cb_info.u.pfnSetInstanceLoaderData = SetInstanceLoaderData;
+
+        info.pNext = &cb_info;
+    }
+
+    if (override_layers_.Count()) {
+        info.enabledLayerCount = override_layers_.Count();
+        info.ppEnabledLayerNames = override_layers_.Names();
+    }
+
+    if (override_extensions_.Count()) {
+        info.enabledExtensionCount = override_extensions_.Count();
+        info.ppEnabledExtensionNames = override_extensions_.Names();
+    }
+}
+
+void LayerChain::ModifyCreateInfo(VkDeviceCreateInfo& info) {
+    if (layer_count_) {
+        auto& link_info = device_chain_info_[1];
+        link_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+        link_info.pNext = info.pNext;
+        link_info.function = VK_LAYER_FUNCTION_LINK;
+        link_info.u.pLayerInfo = &layers_[0].device_link;
+
+        auto& cb_info = device_chain_info_[0];
+        cb_info.sType = VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO;
+        cb_info.pNext = &link_info;
+        cb_info.function = VK_LAYER_FUNCTION_DATA_CALLBACK;
+        cb_info.u.pfnSetDeviceLoaderData = SetDeviceLoaderData;
+
+        info.pNext = &cb_info;
+    }
+
+    if (override_layers_.Count()) {
+        info.enabledLayerCount = override_layers_.Count();
+        info.ppEnabledLayerNames = override_layers_.Names();
+    }
+
+    if (override_extensions_.Count()) {
+        info.enabledExtensionCount = override_extensions_.Count();
+        info.ppEnabledExtensionNames = override_extensions_.Names();
+    }
+}
+
+VkResult LayerChain::Create(const VkInstanceCreateInfo* create_info,
+                            const VkAllocationCallbacks* allocator,
+                            VkInstance* instance_out) {
+    VkResult result = ValidateExtensions(create_info->ppEnabledExtensionNames,
+                                         create_info->enabledExtensionCount);
+    if (result != VK_SUCCESS)
+        return result;
+
+    // call down the chain
+    PFN_vkCreateInstance create_instance =
+        reinterpret_cast<PFN_vkCreateInstance>(
+            get_instance_proc_addr_(VK_NULL_HANDLE, "vkCreateInstance"));
+    VkInstance instance;
+    result = create_instance(create_info, allocator, &instance);
+    if (result != VK_SUCCESS)
+        return result;
+
+    // initialize InstanceData
+    InstanceData& data = GetData(instance);
+
+    if (!InitDispatchTable(instance, get_instance_proc_addr_,
+                           enabled_extensions_)) {
+        if (data.dispatch.DestroyInstance)
+            data.dispatch.DestroyInstance(instance, allocator);
+
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // install debug report callback
+    if (override_extensions_.InstallDebugCallback()) {
+        PFN_vkCreateDebugReportCallbackEXT create_debug_report_callback =
+            reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+                get_instance_proc_addr_(instance,
+                                        "vkCreateDebugReportCallbackEXT"));
+        data.destroy_debug_callback =
+            reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+                get_instance_proc_addr_(instance,
+                                        "vkDestroyDebugReportCallbackEXT"));
+        if (!create_debug_report_callback || !data.destroy_debug_callback) {
+            ALOGE("Broken VK_EXT_debug_report support");
+            data.dispatch.DestroyInstance(instance, allocator);
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+
+        VkDebugReportCallbackCreateInfoEXT debug_callback_info = {};
+        debug_callback_info.sType =
+            VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+        debug_callback_info.flags =
+            VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
+        debug_callback_info.pfnCallback = DebugReportCallback;
+
+        VkDebugReportCallbackEXT debug_callback;
+        result = create_debug_report_callback(instance, &debug_callback_info,
+                                              nullptr, &debug_callback);
+        if (result != VK_SUCCESS) {
+            ALOGE("Failed to install debug report callback");
+            data.dispatch.DestroyInstance(instance, allocator);
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+
+        data.debug_callback = debug_callback;
+
+        ALOGI("Installed debug report callback");
+    }
+
+    StealLayers(data);
+
+    *instance_out = instance;
+
+    return VK_SUCCESS;
+}
+
+VkResult LayerChain::Create(VkPhysicalDevice physical_dev,
+                            const VkDeviceCreateInfo* create_info,
+                            const VkAllocationCallbacks* allocator,
+                            VkDevice* dev_out) {
+    VkResult result =
+        ValidateExtensions(physical_dev, create_info->ppEnabledExtensionNames,
+                           create_info->enabledExtensionCount);
+    if (result != VK_SUCCESS)
+        return result;
+
+    // call down the chain
+    PFN_vkCreateDevice create_device =
+        GetData(physical_dev).dispatch.CreateDevice;
+    VkDevice dev;
+    result = create_device(physical_dev, create_info, allocator, &dev);
+    if (result != VK_SUCCESS)
+        return result;
+
+    // initialize DeviceData
+    DeviceData& data = GetData(dev);
+
+    if (!InitDispatchTable(dev, get_device_proc_addr_, enabled_extensions_)) {
+        if (data.dispatch.DestroyDevice)
+            data.dispatch.DestroyDevice(dev, allocator);
+
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // no StealLayers so that active layers are destroyed with this
+    // LayerChain
+    *dev_out = dev;
+
+    return VK_SUCCESS;
+}
+
+VkResult LayerChain::ValidateExtensions(const char* const* extension_names,
+                                        uint32_t extension_count) {
+    if (!extension_count)
+        return VK_SUCCESS;
+
+    // query driver instance extensions
+    uint32_t count;
+    VkResult result =
+        EnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
+    if (result == VK_SUCCESS && count) {
+        driver_extensions_ = AllocateDriverExtensionArray(count);
+        result = (driver_extensions_) ? EnumerateInstanceExtensionProperties(
+                                            nullptr, &count, driver_extensions_)
+                                      : VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+    if (result != VK_SUCCESS)
+        return result;
+
+    driver_extension_count_ = count;
+
+    for (uint32_t i = 0; i < extension_count; i++) {
+        const char* name = extension_names[i];
+        if (!IsLayerExtension(name) && !IsDriverExtension(name)) {
+            ALOGE("Failed to enable missing instance extension %s", name);
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+
+        auto ext_bit = driver::GetProcHookExtension(name);
+        if (ext_bit != driver::ProcHook::EXTENSION_UNKNOWN)
+            enabled_extensions_.set(ext_bit);
+    }
+
+    return VK_SUCCESS;
+}
+
+VkResult LayerChain::ValidateExtensions(VkPhysicalDevice physical_dev,
+                                        const char* const* extension_names,
+                                        uint32_t extension_count) {
+    if (!extension_count)
+        return VK_SUCCESS;
+
+    // query driver device extensions
+    uint32_t count;
+    VkResult result = EnumerateDeviceExtensionProperties(physical_dev, nullptr,
+                                                         &count, nullptr);
+    if (result == VK_SUCCESS && count) {
+        driver_extensions_ = AllocateDriverExtensionArray(count);
+        result = (driver_extensions_)
+                     ? EnumerateDeviceExtensionProperties(
+                           physical_dev, nullptr, &count, driver_extensions_)
+                     : VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+    if (result != VK_SUCCESS)
+        return result;
+
+    driver_extension_count_ = count;
+
+    for (uint32_t i = 0; i < extension_count; i++) {
+        const char* name = extension_names[i];
+        if (!IsLayerExtension(name) && !IsDriverExtension(name)) {
+            ALOGE("Failed to enable missing device extension %s", name);
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+
+        auto ext_bit = driver::GetProcHookExtension(name);
+        if (ext_bit != driver::ProcHook::EXTENSION_UNKNOWN)
+            enabled_extensions_.set(ext_bit);
+    }
+
+    return VK_SUCCESS;
+}
+
+VkExtensionProperties* LayerChain::AllocateDriverExtensionArray(
+    uint32_t count) const {
+    return reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
+        allocator_.pUserData, sizeof(VkExtensionProperties) * count,
+        alignof(VkExtensionProperties), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+}
+
+bool LayerChain::IsLayerExtension(const char* name) const {
+    if (is_instance_) {
+        for (uint32_t i = 0; i < layer_count_; i++) {
+            const ActiveLayer& layer = layers_[i];
+            if (FindLayerInstanceExtension(*layer.ref, name))
+                return true;
+        }
+    } else {
+        for (uint32_t i = 0; i < layer_count_; i++) {
+            const ActiveLayer& layer = layers_[i];
+            if (FindLayerDeviceExtension(*layer.ref, name))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+bool LayerChain::IsDriverExtension(const char* name) const {
+    for (uint32_t i = 0; i < driver_extension_count_; i++) {
+        if (strcmp(driver_extensions_[i].extensionName, name) == 0)
+            return true;
+    }
+
+    return false;
+}
+
+template <typename DataType>
+void LayerChain::StealLayers(DataType& data) {
+    data.layers = layers_;
+    data.layer_count = layer_count_;
+
+    layers_ = nullptr;
+    layer_count_ = 0;
+}
+
+void LayerChain::DestroyLayers(ActiveLayer* layers,
+                               uint32_t count,
+                               const VkAllocationCallbacks& allocator) {
+    for (uint32_t i = 0; i < count; i++)
+        layers[i].ref.~LayerRef();
+
+    allocator.pfnFree(allocator.pUserData, layers);
+}
+
+VkResult LayerChain::SetInstanceLoaderData(VkInstance instance, void* object) {
+    driver::InstanceDispatchable dispatchable =
+        reinterpret_cast<driver::InstanceDispatchable>(object);
+
+    return (driver::SetDataInternal(dispatchable, &driver::GetData(instance)))
+               ? VK_SUCCESS
+               : VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VkResult LayerChain::SetDeviceLoaderData(VkDevice device, void* object) {
+    driver::DeviceDispatchable dispatchable =
+        reinterpret_cast<driver::DeviceDispatchable>(object);
+
+    return (driver::SetDataInternal(dispatchable, &driver::GetData(device)))
+               ? VK_SUCCESS
+               : VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VkBool32 LayerChain::DebugReportCallback(VkDebugReportFlagsEXT flags,
+                                         VkDebugReportObjectTypeEXT obj_type,
+                                         uint64_t obj,
+                                         size_t location,
+                                         int32_t msg_code,
+                                         const char* layer_prefix,
+                                         const char* msg,
+                                         void* user_data) {
+    int prio;
+
+    if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
+        prio = ANDROID_LOG_ERROR;
+    else if (flags & (VK_DEBUG_REPORT_WARNING_BIT_EXT |
+                      VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT))
+        prio = ANDROID_LOG_WARN;
+    else if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
+        prio = ANDROID_LOG_INFO;
+    else if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
+        prio = ANDROID_LOG_DEBUG;
+    else
+        prio = ANDROID_LOG_UNKNOWN;
+
+    LOG_PRI(prio, LOG_TAG, "[%s] Code %d : %s", layer_prefix, msg_code, msg);
+
+    (void)obj_type;
+    (void)obj;
+    (void)location;
+    (void)user_data;
+
+    return false;
+}
+
+VkResult LayerChain::CreateInstance(const VkInstanceCreateInfo* create_info,
+                                    const VkAllocationCallbacks* allocator,
+                                    VkInstance* instance_out) {
+    LayerChain chain(true,
+                     (allocator) ? *allocator : driver::GetDefaultAllocator());
+
+    VkResult result = chain.ActivateLayers(create_info->ppEnabledLayerNames,
+                                           create_info->enabledLayerCount,
+                                           create_info->ppEnabledExtensionNames,
+                                           create_info->enabledExtensionCount);
+    if (result != VK_SUCCESS)
+        return result;
+
+    // use a local create info when the chain is not empty
+    VkInstanceCreateInfo local_create_info;
+    if (!chain.Empty()) {
+        local_create_info = *create_info;
+        chain.ModifyCreateInfo(local_create_info);
+        create_info = &local_create_info;
+    }
+
+    return chain.Create(create_info, allocator, instance_out);
+}
+
+VkResult LayerChain::CreateDevice(VkPhysicalDevice physical_dev,
+                                  const VkDeviceCreateInfo* create_info,
+                                  const VkAllocationCallbacks* allocator,
+                                  VkDevice* dev_out) {
+    LayerChain chain(false, (allocator)
+                                ? *allocator
+                                : driver::GetData(physical_dev).allocator);
+
+    VkResult result = chain.ActivateLayers(
+        physical_dev, create_info->ppEnabledLayerNames,
+        create_info->enabledLayerCount, create_info->ppEnabledExtensionNames,
+        create_info->enabledExtensionCount);
+    if (result != VK_SUCCESS)
+        return result;
+
+    // use a local create info when the chain is not empty
+    VkDeviceCreateInfo local_create_info;
+    if (!chain.Empty()) {
+        local_create_info = *create_info;
+        chain.ModifyCreateInfo(local_create_info);
+        create_info = &local_create_info;
+    }
+
+    return chain.Create(physical_dev, create_info, allocator, dev_out);
+}
+
+void LayerChain::DestroyInstance(VkInstance instance,
+                                 const VkAllocationCallbacks* allocator) {
+    InstanceData& data = GetData(instance);
+
+    if (data.debug_callback != VK_NULL_HANDLE)
+        data.destroy_debug_callback(instance, data.debug_callback, allocator);
+
+    ActiveLayer* layers = reinterpret_cast<ActiveLayer*>(data.layers);
+    uint32_t layer_count = data.layer_count;
+
+    VkAllocationCallbacks local_allocator;
+    if (!allocator)
+        local_allocator = driver::GetData(instance).allocator;
+
+    // this also destroys InstanceData
+    data.dispatch.DestroyInstance(instance, allocator);
+
+    DestroyLayers(layers, layer_count,
+                  (allocator) ? *allocator : local_allocator);
+}
+
+void LayerChain::DestroyDevice(VkDevice device,
+                               const VkAllocationCallbacks* allocator) {
+    DeviceData& data = GetData(device);
+    // this also destroys DeviceData
+    data.dispatch.DestroyDevice(device, allocator);
+}
+
+const LayerChain::ActiveLayer* LayerChain::GetActiveLayers(
+    VkPhysicalDevice physical_dev,
+    uint32_t& count) {
+    count = GetData(physical_dev).layer_count;
+    return reinterpret_cast<const ActiveLayer*>(GetData(physical_dev).layers);
+}
+
+// ----------------------------------------------------------------------------
+
+bool EnsureInitialized() {
+    static std::once_flag once_flag;
+    static bool initialized;
+
+    std::call_once(once_flag, []() {
+        if (driver::OpenHAL()) {
+            DiscoverLayers();
+            initialized = true;
+        }
+    });
+
+    return initialized;
+}
+
+}  // anonymous namespace
+
+VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+                        const VkAllocationCallbacks* pAllocator,
+                        VkInstance* pInstance) {
+    if (!EnsureInitialized())
+        return VK_ERROR_INITIALIZATION_FAILED;
+
+    return LayerChain::CreateInstance(pCreateInfo, pAllocator, pInstance);
+}
+
+void DestroyInstance(VkInstance instance,
+                     const VkAllocationCallbacks* pAllocator) {
+    if (instance != VK_NULL_HANDLE)
+        LayerChain::DestroyInstance(instance, pAllocator);
+}
+
+VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+                      const VkDeviceCreateInfo* pCreateInfo,
+                      const VkAllocationCallbacks* pAllocator,
+                      VkDevice* pDevice) {
+    return LayerChain::CreateDevice(physicalDevice, pCreateInfo, pAllocator,
+                                    pDevice);
+}
+
+void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+    if (device != VK_NULL_HANDLE)
+        LayerChain::DestroyDevice(device, pAllocator);
+}
+
+VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
+                                          VkLayerProperties* pProperties) {
+    if (!EnsureInitialized())
+        return VK_ERROR_INITIALIZATION_FAILED;
+
+    uint32_t count = GetLayerCount();
+
+    if (!pProperties) {
+        *pPropertyCount = count;
+        return VK_SUCCESS;
+    }
+
+    uint32_t copied = std::min(*pPropertyCount, count);
+    for (uint32_t i = 0; i < copied; i++)
+        pProperties[i] = GetLayerProperties(GetLayer(i));
+    *pPropertyCount = copied;
+
+    return (copied == count) ? VK_SUCCESS : VK_INCOMPLETE;
+}
+
+VkResult EnumerateInstanceExtensionProperties(
+    const char* pLayerName,
+    uint32_t* pPropertyCount,
+    VkExtensionProperties* pProperties) {
+    if (!EnsureInitialized())
+        return VK_ERROR_INITIALIZATION_FAILED;
+
+    if (pLayerName) {
+        const Layer* layer = FindLayer(pLayerName);
+        if (!layer)
+            return VK_ERROR_LAYER_NOT_PRESENT;
+
+        uint32_t count;
+        const VkExtensionProperties* props =
+            GetLayerInstanceExtensions(*layer, count);
+
+        if (!pProperties || *pPropertyCount > count)
+            *pPropertyCount = count;
+        if (pProperties)
+            std::copy(props, props + *pPropertyCount, pProperties);
+
+        return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+    }
+
+    // TODO how about extensions from implicitly enabled layers?
+    return vulkan::driver::EnumerateInstanceExtensionProperties(
+        nullptr, pPropertyCount, pProperties);
+}
+
+VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
+                                        uint32_t* pPropertyCount,
+                                        VkLayerProperties* pProperties) {
+    uint32_t count;
+    const LayerChain::ActiveLayer* layers =
+        LayerChain::GetActiveLayers(physicalDevice, count);
+
+    if (!pProperties) {
+        *pPropertyCount = count;
+        return VK_SUCCESS;
+    }
+
+    uint32_t copied = std::min(*pPropertyCount, count);
+    for (uint32_t i = 0; i < copied; i++)
+        pProperties[i] = GetLayerProperties(*layers[i].ref);
+    *pPropertyCount = copied;
+
+    return (copied == count) ? VK_SUCCESS : VK_INCOMPLETE;
+}
+
+VkResult EnumerateDeviceExtensionProperties(
+    VkPhysicalDevice physicalDevice,
+    const char* pLayerName,
+    uint32_t* pPropertyCount,
+    VkExtensionProperties* pProperties) {
+    if (pLayerName) {
+        // EnumerateDeviceLayerProperties enumerates active layers for
+        // backward compatibility.  The extension query here should work for
+        // all layers.
+        const Layer* layer = FindLayer(pLayerName);
+        if (!layer)
+            return VK_ERROR_LAYER_NOT_PRESENT;
+
+        uint32_t count;
+        const VkExtensionProperties* props =
+            GetLayerDeviceExtensions(*layer, count);
+
+        if (!pProperties || *pPropertyCount > count)
+            *pPropertyCount = count;
+        if (pProperties)
+            std::copy(props, props + *pPropertyCount, pProperties);
+
+        return *pPropertyCount < count ? VK_INCOMPLETE : VK_SUCCESS;
+    }
+
+    // TODO how about extensions from implicitly enabled layers?
+    const InstanceData& data = GetData(physicalDevice);
+    return data.dispatch.EnumerateDeviceExtensionProperties(
+        physicalDevice, nullptr, pPropertyCount, pProperties);
+}
+
+}  // namespace api
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/api.h b/vulkan/libvulkan/api.h
new file mode 100644
index 0000000..ded7d17
--- /dev/null
+++ b/vulkan/libvulkan/api.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LIBVULKAN_API_H
+#define LIBVULKAN_API_H 1
+
+#include <vulkan/vulkan.h>
+#include "api_gen.h"
+#include "driver.h"
+
+namespace vulkan {
+namespace api {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+// clang-format on
+
+inline InstanceData& GetData(VkInstance instance) {
+    return driver::GetData(instance).opaque_api_data;
+}
+
+inline InstanceData& GetData(VkPhysicalDevice physical_dev) {
+    return driver::GetData(physical_dev).opaque_api_data;
+}
+
+inline DeviceData& GetData(VkDevice dev) {
+    return driver::GetData(dev).opaque_api_data;
+}
+
+inline DeviceData& GetData(VkQueue queue) {
+    return driver::GetData(queue).opaque_api_data;
+}
+
+inline DeviceData& GetData(VkCommandBuffer cmd) {
+    return driver::GetData(cmd).opaque_api_data;
+}
+
+}  // namespace api
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_API_H
diff --git a/vulkan/libvulkan/api_gen.cpp b/vulkan/libvulkan/api_gen.cpp
new file mode 100644
index 0000000..fe4136f
--- /dev/null
+++ b/vulkan/libvulkan/api_gen.cpp
@@ -0,0 +1,1243 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+
+#include "api.h"
+
+namespace vulkan {
+namespace api {
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(obj, proc)                                           \
+    do {                                                               \
+        data.dispatch.proc =                                           \
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
+        if (UNLIKELY(!data.dispatch.proc)) {                           \
+            ALOGE("missing " #obj " proc: vk" #proc);                  \
+            success = false;                                           \
+        }                                                              \
+    } while (0)
+
+// Exported extension functions may be invoked even when their extensions
+// are disabled.  Dispatch to stubs when that happens.
+#define INIT_PROC_EXT(ext, obj, proc)            \
+    do {                                         \
+        if (extensions[driver::ProcHook::ext])   \
+            INIT_PROC(obj, proc);                \
+        else                                     \
+            data.dispatch.proc = disabled##proc; \
+    } while (0)
+
+namespace {
+
+// clang-format off
+
+VKAPI_ATTR void disabledDestroySurfaceKHR(VkInstance, VkSurfaceKHR, const VkAllocationCallbacks*) {
+    ALOGE("VK_KHR_surface not enabled. vkDestroySurfaceKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice, uint32_t, VkSurfaceKHR, VkBool32*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceSupportKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice, VkSurfaceKHR, VkSurfaceCapabilitiesKHR*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceCapabilitiesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkSurfaceFormatKHR*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfaceFormatsKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice, VkSurfaceKHR, uint32_t*, VkPresentModeKHR*) {
+    ALOGE("VK_KHR_surface not enabled. vkGetPhysicalDeviceSurfacePresentModesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateSwapchainKHR(VkDevice, const VkSwapchainCreateInfoKHR*, const VkAllocationCallbacks*, VkSwapchainKHR*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR void disabledDestroySwapchainKHR(VkDevice, VkSwapchainKHR, const VkAllocationCallbacks*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
+}
+
+VKAPI_ATTR VkResult disabledGetSwapchainImagesKHR(VkDevice, VkSwapchainKHR, uint32_t*, VkImage*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledAcquireNextImageKHR(VkDevice, VkSwapchainKHR, uint64_t, VkSemaphore, VkFence, uint32_t*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledQueuePresentKHR(VkQueue, const VkPresentInfoKHR*) {
+    ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult disabledCreateAndroidSurfaceKHR(VkInstance, const VkAndroidSurfaceCreateInfoKHR*, const VkAllocationCallbacks*, VkSurfaceKHR*) {
+    ALOGE("VK_KHR_android_surface not enabled. vkCreateAndroidSurfaceKHR not executed.");
+    return VK_SUCCESS;
+}
+
+// clang-format on
+
+}  // anonymous
+
+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;
+
+    // clang-format off
+    INIT_PROC(instance, DestroyInstance);
+    INIT_PROC(instance, EnumeratePhysicalDevices);
+    INIT_PROC(instance, GetInstanceProcAddr);
+    INIT_PROC(instance, GetPhysicalDeviceProperties);
+    INIT_PROC(instance, GetPhysicalDeviceQueueFamilyProperties);
+    INIT_PROC(instance, GetPhysicalDeviceMemoryProperties);
+    INIT_PROC(instance, GetPhysicalDeviceFeatures);
+    INIT_PROC(instance, GetPhysicalDeviceFormatProperties);
+    INIT_PROC(instance, GetPhysicalDeviceImageFormatProperties);
+    INIT_PROC(instance, CreateDevice);
+    INIT_PROC(instance, EnumerateDeviceLayerProperties);
+    INIT_PROC(instance, EnumerateDeviceExtensionProperties);
+    INIT_PROC(instance, GetPhysicalDeviceSparseImageFormatProperties);
+    INIT_PROC_EXT(KHR_surface, instance, DestroySurfaceKHR);
+    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceSupportKHR);
+    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
+    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfaceFormatsKHR);
+    INIT_PROC_EXT(KHR_surface, instance, GetPhysicalDeviceSurfacePresentModesKHR);
+    INIT_PROC_EXT(KHR_android_surface, instance, CreateAndroidSurfaceKHR);
+    // clang-format on
+
+    return success;
+}
+
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;
+
+    // clang-format off
+    INIT_PROC(dev, GetDeviceProcAddr);
+    INIT_PROC(dev, DestroyDevice);
+    INIT_PROC(dev, GetDeviceQueue);
+    INIT_PROC(dev, QueueSubmit);
+    INIT_PROC(dev, QueueWaitIdle);
+    INIT_PROC(dev, DeviceWaitIdle);
+    INIT_PROC(dev, AllocateMemory);
+    INIT_PROC(dev, FreeMemory);
+    INIT_PROC(dev, MapMemory);
+    INIT_PROC(dev, UnmapMemory);
+    INIT_PROC(dev, FlushMappedMemoryRanges);
+    INIT_PROC(dev, InvalidateMappedMemoryRanges);
+    INIT_PROC(dev, GetDeviceMemoryCommitment);
+    INIT_PROC(dev, GetBufferMemoryRequirements);
+    INIT_PROC(dev, BindBufferMemory);
+    INIT_PROC(dev, GetImageMemoryRequirements);
+    INIT_PROC(dev, BindImageMemory);
+    INIT_PROC(dev, GetImageSparseMemoryRequirements);
+    INIT_PROC(dev, QueueBindSparse);
+    INIT_PROC(dev, CreateFence);
+    INIT_PROC(dev, DestroyFence);
+    INIT_PROC(dev, ResetFences);
+    INIT_PROC(dev, GetFenceStatus);
+    INIT_PROC(dev, WaitForFences);
+    INIT_PROC(dev, CreateSemaphore);
+    INIT_PROC(dev, DestroySemaphore);
+    INIT_PROC(dev, CreateEvent);
+    INIT_PROC(dev, DestroyEvent);
+    INIT_PROC(dev, GetEventStatus);
+    INIT_PROC(dev, SetEvent);
+    INIT_PROC(dev, ResetEvent);
+    INIT_PROC(dev, CreateQueryPool);
+    INIT_PROC(dev, DestroyQueryPool);
+    INIT_PROC(dev, GetQueryPoolResults);
+    INIT_PROC(dev, CreateBuffer);
+    INIT_PROC(dev, DestroyBuffer);
+    INIT_PROC(dev, CreateBufferView);
+    INIT_PROC(dev, DestroyBufferView);
+    INIT_PROC(dev, CreateImage);
+    INIT_PROC(dev, DestroyImage);
+    INIT_PROC(dev, GetImageSubresourceLayout);
+    INIT_PROC(dev, CreateImageView);
+    INIT_PROC(dev, DestroyImageView);
+    INIT_PROC(dev, CreateShaderModule);
+    INIT_PROC(dev, DestroyShaderModule);
+    INIT_PROC(dev, CreatePipelineCache);
+    INIT_PROC(dev, DestroyPipelineCache);
+    INIT_PROC(dev, GetPipelineCacheData);
+    INIT_PROC(dev, MergePipelineCaches);
+    INIT_PROC(dev, CreateGraphicsPipelines);
+    INIT_PROC(dev, CreateComputePipelines);
+    INIT_PROC(dev, DestroyPipeline);
+    INIT_PROC(dev, CreatePipelineLayout);
+    INIT_PROC(dev, DestroyPipelineLayout);
+    INIT_PROC(dev, CreateSampler);
+    INIT_PROC(dev, DestroySampler);
+    INIT_PROC(dev, CreateDescriptorSetLayout);
+    INIT_PROC(dev, DestroyDescriptorSetLayout);
+    INIT_PROC(dev, CreateDescriptorPool);
+    INIT_PROC(dev, DestroyDescriptorPool);
+    INIT_PROC(dev, ResetDescriptorPool);
+    INIT_PROC(dev, AllocateDescriptorSets);
+    INIT_PROC(dev, FreeDescriptorSets);
+    INIT_PROC(dev, UpdateDescriptorSets);
+    INIT_PROC(dev, CreateFramebuffer);
+    INIT_PROC(dev, DestroyFramebuffer);
+    INIT_PROC(dev, CreateRenderPass);
+    INIT_PROC(dev, DestroyRenderPass);
+    INIT_PROC(dev, GetRenderAreaGranularity);
+    INIT_PROC(dev, CreateCommandPool);
+    INIT_PROC(dev, DestroyCommandPool);
+    INIT_PROC(dev, ResetCommandPool);
+    INIT_PROC(dev, AllocateCommandBuffers);
+    INIT_PROC(dev, FreeCommandBuffers);
+    INIT_PROC(dev, BeginCommandBuffer);
+    INIT_PROC(dev, EndCommandBuffer);
+    INIT_PROC(dev, ResetCommandBuffer);
+    INIT_PROC(dev, CmdBindPipeline);
+    INIT_PROC(dev, CmdSetViewport);
+    INIT_PROC(dev, CmdSetScissor);
+    INIT_PROC(dev, CmdSetLineWidth);
+    INIT_PROC(dev, CmdSetDepthBias);
+    INIT_PROC(dev, CmdSetBlendConstants);
+    INIT_PROC(dev, CmdSetDepthBounds);
+    INIT_PROC(dev, CmdSetStencilCompareMask);
+    INIT_PROC(dev, CmdSetStencilWriteMask);
+    INIT_PROC(dev, CmdSetStencilReference);
+    INIT_PROC(dev, CmdBindDescriptorSets);
+    INIT_PROC(dev, CmdBindIndexBuffer);
+    INIT_PROC(dev, CmdBindVertexBuffers);
+    INIT_PROC(dev, CmdDraw);
+    INIT_PROC(dev, CmdDrawIndexed);
+    INIT_PROC(dev, CmdDrawIndirect);
+    INIT_PROC(dev, CmdDrawIndexedIndirect);
+    INIT_PROC(dev, CmdDispatch);
+    INIT_PROC(dev, CmdDispatchIndirect);
+    INIT_PROC(dev, CmdCopyBuffer);
+    INIT_PROC(dev, CmdCopyImage);
+    INIT_PROC(dev, CmdBlitImage);
+    INIT_PROC(dev, CmdCopyBufferToImage);
+    INIT_PROC(dev, CmdCopyImageToBuffer);
+    INIT_PROC(dev, CmdUpdateBuffer);
+    INIT_PROC(dev, CmdFillBuffer);
+    INIT_PROC(dev, CmdClearColorImage);
+    INIT_PROC(dev, CmdClearDepthStencilImage);
+    INIT_PROC(dev, CmdClearAttachments);
+    INIT_PROC(dev, CmdResolveImage);
+    INIT_PROC(dev, CmdSetEvent);
+    INIT_PROC(dev, CmdResetEvent);
+    INIT_PROC(dev, CmdWaitEvents);
+    INIT_PROC(dev, CmdPipelineBarrier);
+    INIT_PROC(dev, CmdBeginQuery);
+    INIT_PROC(dev, CmdEndQuery);
+    INIT_PROC(dev, CmdResetQueryPool);
+    INIT_PROC(dev, CmdWriteTimestamp);
+    INIT_PROC(dev, CmdCopyQueryPoolResults);
+    INIT_PROC(dev, CmdPushConstants);
+    INIT_PROC(dev, CmdBeginRenderPass);
+    INIT_PROC(dev, CmdNextSubpass);
+    INIT_PROC(dev, CmdEndRenderPass);
+    INIT_PROC(dev, CmdExecuteCommands);
+    INIT_PROC_EXT(KHR_swapchain, dev, CreateSwapchainKHR);
+    INIT_PROC_EXT(KHR_swapchain, dev, DestroySwapchainKHR);
+    INIT_PROC_EXT(KHR_swapchain, dev, GetSwapchainImagesKHR);
+    INIT_PROC_EXT(KHR_swapchain, dev, AcquireNextImageKHR);
+    INIT_PROC_EXT(KHR_swapchain, dev, QueuePresentKHR);
+    // clang-format on
+
+    return success;
+}
+
+}  // namespace api
+}  // namespace vulkan
+
+// clang-format off
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
+    // call into api.cpp
+    return vulkan::api::CreateInstance(pCreateInfo, pAllocator, pInstance);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator) {
+    // call into api.cpp
+    vulkan::api::DestroyInstance(instance, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices) {
+    return vulkan::api::GetData(instance).dispatch.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR PFN_vkVoidFunction vkGetDeviceProcAddr(VkDevice device, const char* pName) {
+    if (device == VK_NULL_HANDLE) {
+        ALOGE("vkGetDeviceProcAddr called with invalid device");
+        return nullptr;
+    }
+
+    static const char* const known_non_device_names[] = {
+        "vkCreateAndroidSurfaceKHR",
+        "vkCreateDebugReportCallbackEXT",
+        "vkCreateDevice",
+        "vkCreateInstance",
+        "vkDebugReportMessageEXT",
+        "vkDestroyDebugReportCallbackEXT",
+        "vkDestroyInstance",
+        "vkDestroySurfaceKHR",
+        "vkEnumerateDeviceExtensionProperties",
+        "vkEnumerateDeviceLayerProperties",
+        "vkEnumerateInstanceExtensionProperties",
+        "vkEnumerateInstanceLayerProperties",
+        "vkEnumeratePhysicalDevices",
+        "vkGetInstanceProcAddr",
+        "vkGetPhysicalDeviceFeatures",
+        "vkGetPhysicalDeviceFormatProperties",
+        "vkGetPhysicalDeviceImageFormatProperties",
+        "vkGetPhysicalDeviceMemoryProperties",
+        "vkGetPhysicalDeviceProperties",
+        "vkGetPhysicalDeviceQueueFamilyProperties",
+        "vkGetPhysicalDeviceSparseImageFormatProperties",
+        "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+        "vkGetPhysicalDeviceSurfaceFormatsKHR",
+        "vkGetPhysicalDeviceSurfacePresentModesKHR",
+        "vkGetPhysicalDeviceSurfaceSupportKHR",
+    };
+    // clang-format on
+    constexpr size_t count =
+        sizeof(known_non_device_names) / sizeof(known_non_device_names[0]);
+    if (!pName ||
+        std::binary_search(
+            known_non_device_names, known_non_device_names + count, pName,
+            [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
+        ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
+        return nullptr;
+    }
+    // clang-format off
+
+    if (strcmp(pName, "vkGetDeviceProcAddr") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr);
+    if (strcmp(pName, "vkDestroyDevice") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyDevice);
+
+    return vulkan::api::GetData(device).dispatch.GetDeviceProcAddr(device, pName);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
+    // global functions
+    if (!instance) {
+        if (strcmp(pName, "vkCreateInstance") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::CreateInstance);
+        if (strcmp(pName, "vkEnumerateInstanceLayerProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateInstanceLayerProperties);
+        if (strcmp(pName, "vkEnumerateInstanceExtensionProperties") == 0) return reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateInstanceExtensionProperties);
+
+        ALOGE("vkGetInstanceProcAddr called with %s without instance",  pName);
+        return nullptr;
+    }
+
+    static const struct Hook {
+        const char* name;
+        PFN_vkVoidFunction proc;
+    } hooks[] = {
+        { "vkAcquireNextImageKHR", reinterpret_cast<PFN_vkVoidFunction>(vkAcquireNextImageKHR) },
+        { "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateCommandBuffers) },
+        { "vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateDescriptorSets) },
+        { "vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(vkAllocateMemory) },
+        { "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkBeginCommandBuffer) },
+        { "vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindBufferMemory) },
+        { "vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(vkBindImageMemory) },
+        { "vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginQuery) },
+        { "vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBeginRenderPass) },
+        { "vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindDescriptorSets) },
+        { "vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindIndexBuffer) },
+        { "vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindPipeline) },
+        { "vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBindVertexBuffers) },
+        { "vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdBlitImage) },
+        { "vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearAttachments) },
+        { "vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearColorImage) },
+        { "vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdClearDepthStencilImage) },
+        { "vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBuffer) },
+        { "vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyBufferToImage) },
+        { "vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImage) },
+        { "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyImageToBuffer) },
+        { "vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkCmdCopyQueryPoolResults) },
+        { "vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatch) },
+        { "vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDispatchIndirect) },
+        { "vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDraw) },
+        { "vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexed) },
+        { "vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndexedIndirect) },
+        { "vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(vkCmdDrawIndirect) },
+        { "vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndQuery) },
+        { "vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdEndRenderPass) },
+        { "vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(vkCmdExecuteCommands) },
+        { "vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdFillBuffer) },
+        { "vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(vkCmdNextSubpass) },
+        { "vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPipelineBarrier) },
+        { "vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdPushConstants) },
+        { "vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetEvent) },
+        { "vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResetQueryPool) },
+        { "vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(vkCmdResolveImage) },
+        { "vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetBlendConstants) },
+        { "vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetDepthBias) },
+        { "vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetDepthBounds) },
+        { "vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetEvent) },
+        { "vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetLineWidth) },
+        { "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetScissor) },
+        { "vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilCompareMask) },
+        { "vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilReference) },
+        { "vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetStencilWriteMask) },
+        { "vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(vkCmdSetViewport) },
+        { "vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCmdUpdateBuffer) },
+        { "vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWaitEvents) },
+        { "vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(vkCmdWriteTimestamp) },
+        { "vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBuffer) },
+        { "vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateBufferView) },
+        { "vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateCommandPool) },
+        { "vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateComputePipelines) },
+        { "vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorPool) },
+        { "vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreateDescriptorSetLayout) },
+        { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::CreateDevice) },
+        { "vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(vkCreateEvent) },
+        { "vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFence) },
+        { "vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkCreateFramebuffer) },
+        { "vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(vkCreateGraphicsPipelines) },
+        { "vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImage) },
+        { "vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(vkCreateImageView) },
+        { "vkCreateInstance", nullptr },
+        { "vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineCache) },
+        { "vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkCreatePipelineLayout) },
+        { "vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkCreateQueryPool) },
+        { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkCreateRenderPass) },
+        { "vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSampler) },
+        { "vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSemaphore) },
+        { "vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkCreateShaderModule) },
+        { "vkCreateSwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(vkCreateSwapchainKHR) },
+        { "vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBuffer) },
+        { "vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyBufferView) },
+        { "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyCommandPool) },
+        { "vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorPool) },
+        { "vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyDescriptorSetLayout) },
+        { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyDevice) },
+        { "vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyEvent) },
+        { "vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFence) },
+        { "vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyFramebuffer) },
+        { "vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImage) },
+        { "vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyImageView) },
+        { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::DestroyInstance) },
+        { "vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipeline) },
+        { "vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineCache) },
+        { "vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyPipelineLayout) },
+        { "vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyQueryPool) },
+        { "vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyRenderPass) },
+        { "vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySampler) },
+        { "vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySemaphore) },
+        { "vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(vkDestroyShaderModule) },
+        { "vkDestroySwapchainKHR", reinterpret_cast<PFN_vkVoidFunction>(vkDestroySwapchainKHR) },
+        { "vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkDeviceWaitIdle) },
+        { "vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkEndCommandBuffer) },
+        { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateDeviceExtensionProperties) },
+        { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(vulkan::api::EnumerateDeviceLayerProperties) },
+        { "vkEnumerateInstanceExtensionProperties", nullptr },
+        { "vkEnumerateInstanceLayerProperties", nullptr },
+        { "vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkFlushMappedMemoryRanges) },
+        { "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(vkFreeCommandBuffers) },
+        { "vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkFreeDescriptorSets) },
+        { "vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(vkFreeMemory) },
+        { "vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetBufferMemoryRequirements) },
+        { "vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceMemoryCommitment) },
+        { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceProcAddr) },
+        { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(vkGetDeviceQueue) },
+        { "vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetEventStatus) },
+        { "vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(vkGetFenceStatus) },
+        { "vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageMemoryRequirements) },
+        { "vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSparseMemoryRequirements) },
+        { "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(vkGetImageSubresourceLayout) },
+        { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr) },
+        { "vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(vkGetPipelineCacheData) },
+        { "vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(vkGetQueryPoolResults) },
+        { "vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(vkGetRenderAreaGranularity) },
+        { "vkGetSwapchainImagesKHR", reinterpret_cast<PFN_vkVoidFunction>(vkGetSwapchainImagesKHR) },
+        { "vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(vkInvalidateMappedMemoryRanges) },
+        { "vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkMapMemory) },
+        { "vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(vkMergePipelineCaches) },
+        { "vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(vkQueueBindSparse) },
+        { "vkQueuePresentKHR", reinterpret_cast<PFN_vkVoidFunction>(vkQueuePresentKHR) },
+        { "vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(vkQueueSubmit) },
+        { "vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(vkQueueWaitIdle) },
+        { "vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandBuffer) },
+        { "vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetCommandPool) },
+        { "vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(vkResetDescriptorPool) },
+        { "vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkResetEvent) },
+        { "vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(vkResetFences) },
+        { "vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(vkSetEvent) },
+        { "vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(vkUnmapMemory) },
+        { "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(vkUpdateDescriptorSets) },
+        { "vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(vkWaitForFences) },
+    };
+    // clang-format on
+    constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
+    auto hook = std::lower_bound(
+        hooks, hooks + count, pName,
+        [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
+    if (hook < hooks + count && strcmp(hook->name, pName) == 0) {
+        if (!hook->proc)
+            ALOGE("vkGetInstanceProcAddr called with %s with instance", pName);
+        return hook->proc;
+    }
+    // clang-format off
+
+    return vulkan::api::GetData(instance).dispatch.GetInstanceProcAddr(instance, pName);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties) {
+    vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceProperties(physicalDevice, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties) {
+    vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
+    vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures) {
+    vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
+    vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) {
+    return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
+    // call into api.cpp
+    return vulkan::api::CreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+    // call into api.cpp
+    vulkan::api::DestroyDevice(device, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
+    // call into api.cpp
+    return vulkan::api::EnumerateInstanceLayerProperties(pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
+    // call into api.cpp
+    return vulkan::api::EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
+    // call into api.cpp
+    return vulkan::api::EnumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties) {
+    // call into api.cpp
+    return vulkan::api::EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) {
+    vulkan::api::GetData(device).dispatch.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence) {
+    return vulkan::api::GetData(queue).dispatch.QueueSubmit(queue, submitCount, pSubmits, fence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueueWaitIdle(VkQueue queue) {
+    return vulkan::api::GetData(queue).dispatch.QueueWaitIdle(queue);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkDeviceWaitIdle(VkDevice device) {
+    return vulkan::api::GetData(device).dispatch.DeviceWaitIdle(device);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory) {
+    return vulkan::api::GetData(device).dispatch.AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.FreeMemory(device, memory, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData) {
+    return vulkan::api::GetData(device).dispatch.MapMemory(device, memory, offset, size, flags, ppData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUnmapMemory(VkDevice device, VkDeviceMemory memory) {
+    vulkan::api::GetData(device).dispatch.UnmapMemory(device, memory);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) {
+    return vulkan::api::GetData(device).dispatch.FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges) {
+    return vulkan::api::GetData(device).dispatch.InvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
+    vulkan::api::GetData(device).dispatch.GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements) {
+    vulkan::api::GetData(device).dispatch.GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
+    return vulkan::api::GetData(device).dispatch.BindBufferMemory(device, buffer, memory, memoryOffset);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements) {
+    vulkan::api::GetData(device).dispatch.GetImageMemoryRequirements(device, image, pMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
+    return vulkan::api::GetData(device).dispatch.BindImageMemory(device, image, memory, memoryOffset);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
+    vulkan::api::GetData(device).dispatch.GetImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties) {
+    vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pPropertyCount, pProperties);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) {
+    return vulkan::api::GetData(queue).dispatch.QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence) {
+    return vulkan::api::GetData(device).dispatch.CreateFence(device, pCreateInfo, pAllocator, pFence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyFence(device, fence, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
+    return vulkan::api::GetData(device).dispatch.ResetFences(device, fenceCount, pFences);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetFenceStatus(VkDevice device, VkFence fence) {
+    return vulkan::api::GetData(device).dispatch.GetFenceStatus(device, fence);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
+    return vulkan::api::GetData(device).dispatch.WaitForFences(device, fenceCount, pFences, waitAll, timeout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore) {
+    return vulkan::api::GetData(device).dispatch.CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroySemaphore(device, semaphore, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent) {
+    return vulkan::api::GetData(device).dispatch.CreateEvent(device, pCreateInfo, pAllocator, pEvent);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyEvent(device, event, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetEventStatus(VkDevice device, VkEvent event) {
+    return vulkan::api::GetData(device).dispatch.GetEventStatus(device, event);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkSetEvent(VkDevice device, VkEvent event) {
+    return vulkan::api::GetData(device).dispatch.SetEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetEvent(VkDevice device, VkEvent event) {
+    return vulkan::api::GetData(device).dispatch.ResetEvent(device, event);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool) {
+    return vulkan::api::GetData(device).dispatch.CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyQueryPool(device, queryPool, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) {
+    return vulkan::api::GetData(device).dispatch.GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer) {
+    return vulkan::api::GetData(device).dispatch.CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyBuffer(device, buffer, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView) {
+    return vulkan::api::GetData(device).dispatch.CreateBufferView(device, pCreateInfo, pAllocator, pView);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyBufferView(device, bufferView, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage) {
+    return vulkan::api::GetData(device).dispatch.CreateImage(device, pCreateInfo, pAllocator, pImage);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyImage(device, image, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
+    vulkan::api::GetData(device).dispatch.GetImageSubresourceLayout(device, image, pSubresource, pLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView) {
+    return vulkan::api::GetData(device).dispatch.CreateImageView(device, pCreateInfo, pAllocator, pView);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyImageView(device, imageView, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) {
+    return vulkan::api::GetData(device).dispatch.CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyShaderModule(device, shaderModule, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache) {
+    return vulkan::api::GetData(device).dispatch.CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyPipelineCache(device, pipelineCache, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData) {
+    return vulkan::api::GetData(device).dispatch.GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
+    return vulkan::api::GetData(device).dispatch.MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
+    return vulkan::api::GetData(device).dispatch.CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines) {
+    return vulkan::api::GetData(device).dispatch.CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyPipeline(device, pipeline, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout) {
+    return vulkan::api::GetData(device).dispatch.CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyPipelineLayout(device, pipelineLayout, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler) {
+    return vulkan::api::GetData(device).dispatch.CreateSampler(device, pCreateInfo, pAllocator, pSampler);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroySampler(device, sampler, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout) {
+    return vulkan::api::GetData(device).dispatch.CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool) {
+    return vulkan::api::GetData(device).dispatch.CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyDescriptorPool(device, descriptorPool, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
+    return vulkan::api::GetData(device).dispatch.ResetDescriptorPool(device, descriptorPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets) {
+    return vulkan::api::GetData(device).dispatch.AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets) {
+    return vulkan::api::GetData(device).dispatch.FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
+    vulkan::api::GetData(device).dispatch.UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer) {
+    return vulkan::api::GetData(device).dispatch.CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyFramebuffer(device, framebuffer, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass) {
+    return vulkan::api::GetData(device).dispatch.CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyRenderPass(device, renderPass, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
+    vulkan::api::GetData(device).dispatch.GetRenderAreaGranularity(device, renderPass, pGranularity);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool) {
+    return vulkan::api::GetData(device).dispatch.CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroyCommandPool(device, commandPool, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
+    return vulkan::api::GetData(device).dispatch.ResetCommandPool(device, commandPool, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers) {
+    return vulkan::api::GetData(device).dispatch.AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) {
+    vulkan::api::GetData(device).dispatch.FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo) {
+    return vulkan::api::GetData(commandBuffer).dispatch.BeginCommandBuffer(commandBuffer, pBeginInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
+    return vulkan::api::GetData(commandBuffer).dispatch.EndCommandBuffer(commandBuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
+    return vulkan::api::GetData(commandBuffer).dispatch.ResetCommandBuffer(commandBuffer, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetLineWidth(commandBuffer, lineWidth);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetBlendConstants(commandBuffer, blendConstants);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetStencilReference(commandBuffer, faceMask, reference);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdDrawIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdDrawIndexedIndirect(commandBuffer, buffer, offset, drawCount, stride);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdDispatch(commandBuffer, x, y, z);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdDispatchIndirect(commandBuffer, buffer, offset);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t* pData) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdSetEvent(commandBuffer, event, stageMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdResetEvent(commandBuffer, event, stageMask);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBeginQuery(commandBuffer, queryPool, query, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdEndQuery(commandBuffer, queryPool, query);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, query);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdNextSubpass(commandBuffer, contents);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdEndRenderPass(commandBuffer);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers) {
+    vulkan::api::GetData(commandBuffer).dispatch.CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(instance).dispatch.DestroySurfaceKHR(instance, surface, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32* pSupported) {
+    return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, surface, pSupported);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* pSurfaceCapabilities) {
+    return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, pSurfaceCapabilities);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pSurfaceFormatCount, VkSurfaceFormatKHR* pSurfaceFormats) {
+    return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes) {
+    return vulkan::api::GetData(physicalDevice).dispatch.GetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, pPresentModeCount, pPresentModes);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
+    return vulkan::api::GetData(device).dispatch.CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR void vkDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) {
+    vulkan::api::GetData(device).dispatch.DestroySwapchainKHR(device, swapchain, pAllocator);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
+    return vulkan::api::GetData(device).dispatch.GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) {
+    return vulkan::api::GetData(device).dispatch.AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
+    return vulkan::api::GetData(queue).dispatch.QueuePresentKHR(queue, pPresentInfo);
+}
+
+__attribute__((visibility("default")))
+VKAPI_ATTR VkResult vkCreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface) {
+    return vulkan::api::GetData(instance).dispatch.CreateAndroidSurfaceKHR(instance, pCreateInfo, pAllocator, pSurface);
+}
+
+// clang-format on
diff --git a/vulkan/libvulkan/api_gen.h b/vulkan/libvulkan/api_gen.h
new file mode 100644
index 0000000..779b654
--- /dev/null
+++ b/vulkan/libvulkan/api_gen.h
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H
+
+#include <bitset>
+#include <vulkan/vulkan.h>
+#include "driver_gen.h"
+
+namespace vulkan {
+namespace api {
+
+struct InstanceDispatchTable {
+    // clang-format off
+    PFN_vkDestroyInstance DestroyInstance;
+    PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+    PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties;
+    PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties;
+    PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties;
+    PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures;
+    PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties;
+    PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties;
+    PFN_vkCreateDevice CreateDevice;
+    PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+    PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+    PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
+    PFN_vkDestroySurfaceKHR DestroySurfaceKHR;
+    PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR;
+    PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR;
+    PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR;
+    PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
+    PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
+    // clang-format on
+};
+
+struct DeviceDispatchTable {
+    // clang-format off
+    PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+    PFN_vkDestroyDevice DestroyDevice;
+    PFN_vkGetDeviceQueue GetDeviceQueue;
+    PFN_vkQueueSubmit QueueSubmit;
+    PFN_vkQueueWaitIdle QueueWaitIdle;
+    PFN_vkDeviceWaitIdle DeviceWaitIdle;
+    PFN_vkAllocateMemory AllocateMemory;
+    PFN_vkFreeMemory FreeMemory;
+    PFN_vkMapMemory MapMemory;
+    PFN_vkUnmapMemory UnmapMemory;
+    PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges;
+    PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges;
+    PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment;
+    PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements;
+    PFN_vkBindBufferMemory BindBufferMemory;
+    PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements;
+    PFN_vkBindImageMemory BindImageMemory;
+    PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements;
+    PFN_vkQueueBindSparse QueueBindSparse;
+    PFN_vkCreateFence CreateFence;
+    PFN_vkDestroyFence DestroyFence;
+    PFN_vkResetFences ResetFences;
+    PFN_vkGetFenceStatus GetFenceStatus;
+    PFN_vkWaitForFences WaitForFences;
+    PFN_vkCreateSemaphore CreateSemaphore;
+    PFN_vkDestroySemaphore DestroySemaphore;
+    PFN_vkCreateEvent CreateEvent;
+    PFN_vkDestroyEvent DestroyEvent;
+    PFN_vkGetEventStatus GetEventStatus;
+    PFN_vkSetEvent SetEvent;
+    PFN_vkResetEvent ResetEvent;
+    PFN_vkCreateQueryPool CreateQueryPool;
+    PFN_vkDestroyQueryPool DestroyQueryPool;
+    PFN_vkGetQueryPoolResults GetQueryPoolResults;
+    PFN_vkCreateBuffer CreateBuffer;
+    PFN_vkDestroyBuffer DestroyBuffer;
+    PFN_vkCreateBufferView CreateBufferView;
+    PFN_vkDestroyBufferView DestroyBufferView;
+    PFN_vkCreateImage CreateImage;
+    PFN_vkDestroyImage DestroyImage;
+    PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout;
+    PFN_vkCreateImageView CreateImageView;
+    PFN_vkDestroyImageView DestroyImageView;
+    PFN_vkCreateShaderModule CreateShaderModule;
+    PFN_vkDestroyShaderModule DestroyShaderModule;
+    PFN_vkCreatePipelineCache CreatePipelineCache;
+    PFN_vkDestroyPipelineCache DestroyPipelineCache;
+    PFN_vkGetPipelineCacheData GetPipelineCacheData;
+    PFN_vkMergePipelineCaches MergePipelineCaches;
+    PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines;
+    PFN_vkCreateComputePipelines CreateComputePipelines;
+    PFN_vkDestroyPipeline DestroyPipeline;
+    PFN_vkCreatePipelineLayout CreatePipelineLayout;
+    PFN_vkDestroyPipelineLayout DestroyPipelineLayout;
+    PFN_vkCreateSampler CreateSampler;
+    PFN_vkDestroySampler DestroySampler;
+    PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout;
+    PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout;
+    PFN_vkCreateDescriptorPool CreateDescriptorPool;
+    PFN_vkDestroyDescriptorPool DestroyDescriptorPool;
+    PFN_vkResetDescriptorPool ResetDescriptorPool;
+    PFN_vkAllocateDescriptorSets AllocateDescriptorSets;
+    PFN_vkFreeDescriptorSets FreeDescriptorSets;
+    PFN_vkUpdateDescriptorSets UpdateDescriptorSets;
+    PFN_vkCreateFramebuffer CreateFramebuffer;
+    PFN_vkDestroyFramebuffer DestroyFramebuffer;
+    PFN_vkCreateRenderPass CreateRenderPass;
+    PFN_vkDestroyRenderPass DestroyRenderPass;
+    PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity;
+    PFN_vkCreateCommandPool CreateCommandPool;
+    PFN_vkDestroyCommandPool DestroyCommandPool;
+    PFN_vkResetCommandPool ResetCommandPool;
+    PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+    PFN_vkFreeCommandBuffers FreeCommandBuffers;
+    PFN_vkBeginCommandBuffer BeginCommandBuffer;
+    PFN_vkEndCommandBuffer EndCommandBuffer;
+    PFN_vkResetCommandBuffer ResetCommandBuffer;
+    PFN_vkCmdBindPipeline CmdBindPipeline;
+    PFN_vkCmdSetViewport CmdSetViewport;
+    PFN_vkCmdSetScissor CmdSetScissor;
+    PFN_vkCmdSetLineWidth CmdSetLineWidth;
+    PFN_vkCmdSetDepthBias CmdSetDepthBias;
+    PFN_vkCmdSetBlendConstants CmdSetBlendConstants;
+    PFN_vkCmdSetDepthBounds CmdSetDepthBounds;
+    PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask;
+    PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask;
+    PFN_vkCmdSetStencilReference CmdSetStencilReference;
+    PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets;
+    PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer;
+    PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers;
+    PFN_vkCmdDraw CmdDraw;
+    PFN_vkCmdDrawIndexed CmdDrawIndexed;
+    PFN_vkCmdDrawIndirect CmdDrawIndirect;
+    PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect;
+    PFN_vkCmdDispatch CmdDispatch;
+    PFN_vkCmdDispatchIndirect CmdDispatchIndirect;
+    PFN_vkCmdCopyBuffer CmdCopyBuffer;
+    PFN_vkCmdCopyImage CmdCopyImage;
+    PFN_vkCmdBlitImage CmdBlitImage;
+    PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage;
+    PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer;
+    PFN_vkCmdUpdateBuffer CmdUpdateBuffer;
+    PFN_vkCmdFillBuffer CmdFillBuffer;
+    PFN_vkCmdClearColorImage CmdClearColorImage;
+    PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage;
+    PFN_vkCmdClearAttachments CmdClearAttachments;
+    PFN_vkCmdResolveImage CmdResolveImage;
+    PFN_vkCmdSetEvent CmdSetEvent;
+    PFN_vkCmdResetEvent CmdResetEvent;
+    PFN_vkCmdWaitEvents CmdWaitEvents;
+    PFN_vkCmdPipelineBarrier CmdPipelineBarrier;
+    PFN_vkCmdBeginQuery CmdBeginQuery;
+    PFN_vkCmdEndQuery CmdEndQuery;
+    PFN_vkCmdResetQueryPool CmdResetQueryPool;
+    PFN_vkCmdWriteTimestamp CmdWriteTimestamp;
+    PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults;
+    PFN_vkCmdPushConstants CmdPushConstants;
+    PFN_vkCmdBeginRenderPass CmdBeginRenderPass;
+    PFN_vkCmdNextSubpass CmdNextSubpass;
+    PFN_vkCmdEndRenderPass CmdEndRenderPass;
+    PFN_vkCmdExecuteCommands CmdExecuteCommands;
+    PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
+    PFN_vkDestroySwapchainKHR DestroySwapchainKHR;
+    PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR;
+    PFN_vkAcquireNextImageKHR AcquireNextImageKHR;
+    PFN_vkQueuePresentKHR QueuePresentKHR;
+    // clang-format on
+};
+
+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace api
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_API_GEN_H
diff --git a/vulkan/libvulkan/code-generator.tmpl b/vulkan/libvulkan/code-generator.tmpl
new file mode 100644
index 0000000..3968371
--- /dev/null
+++ b/vulkan/libvulkan/code-generator.tmpl
@@ -0,0 +1,1108 @@
+{{define "Copyright"}}
+/*
+•* Copyright 2016 The Android Open Source Project
+•*
+•* 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.
+•*/
+¶{{end}}
+
+{{Include "../api/templates/vulkan_common.tmpl"}}
+{{Global "clang-format" (Strings "clang-format" "-style=file")}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "api_gen.h"   | Format (Global "clang-format") | Write "api_gen.h"  }}
+{{$ | Macro "api_gen.cpp" | Format (Global "clang-format") | Write "api_gen.cpp"}}
+{{$ | Macro "driver_gen.h" | Format (Global "clang-format") | Write "driver_gen.h"}}
+{{$ | Macro "driver_gen.cpp" | Format (Global "clang-format") | Write "driver_gen.cpp"}}
+
+{{/*
+-------------------------------------------------------------------------------
+  api_gen.h
+-------------------------------------------------------------------------------
+*/}}
+{{define "api_gen.h"}}
+{{Macro "Copyright"}}

+// WARNING: This file is generated. See ../README.md for instructions.

+#ifndef LIBVULKAN_API_GEN_H
+#define LIBVULKAN_API_GEN_H

+#include <bitset>
+#include <vulkan/vulkan.h>
+#include "driver_gen.h"

+namespace vulkan {«
+namespace api {«

+struct InstanceDispatchTable {
+  // clang-format off
+  {{range $f := AllCommands $}}
+    {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
+      {{Macro "C++.DeclareTableEntry" $f}};
+    {{end}}
+  {{end}}
+  // clang-format on
+};

+struct DeviceDispatchTable {
+  // clang-format off
+  {{range $f := AllCommands $}}
+    {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
+      {{Macro "C++.DeclareTableEntry" $f}};
+    {{end}}
+  {{end}}
+  // clang-format on
+};

+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);
+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions);

+»} // namespace api
+»} // namespace vulkan

+#endif // LIBVULKAN_API_GEN_H
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  api_gen.cpp
+-------------------------------------------------------------------------------
+*/}}
+{{define "api_gen.cpp"}}
+{{Macro "Copyright"}}

+// WARNING: This file is generated. See ../README.md for instructions.

+#include <string.h>
+#include <algorithm>
+#include <log/log.h>

+#include "api.h"

+namespace vulkan {«
+namespace api {«

+{{Macro "C++.DefineInitProcMacro" "dispatch"}}

+{{Macro "api.C++.DefineInitProcExtMacro"}}

+namespace {«

+// clang-format off

+{{range $f := AllCommands $}}
+  {{Macro "api.C++.DefineExtensionStub" $f}}
+{{end}}
+// clang-format on

+»} // anonymous

+bool InitDispatchTable(
+    VkInstance instance,
+    PFN_vkGetInstanceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
+    auto& data = GetData(instance);
+    bool success = true;
+    ¶
+    // clang-format off
+    {{range $f := AllCommands $}}
+      {{if (Macro "api.IsInstanceDispatchTableEntry" $f)}}
+        {{Macro "C++.InitProc" $f}}
+      {{end}}
+    {{end}}
+    // clang-format on
+    ¶
+    return success;
+}

+bool InitDispatchTable(
+    VkDevice dev,
+    PFN_vkGetDeviceProcAddr get_proc,
+    const std::bitset<driver::ProcHook::EXTENSION_COUNT> &extensions) {
+    auto& data = GetData(dev);
+    bool success = true;
+    ¶
+    // clang-format off
+    {{range $f := AllCommands $}}
+      {{if (Macro "api.IsDeviceDispatchTableEntry" $f)}}
+        {{Macro "C++.InitProc" $f}}
+      {{end}}
+    {{end}}
+    // clang-format on
+    ¶
+    return success;
+}

+»} // namespace api
+»} // namespace vulkan

+// clang-format off

+{{range $f := AllCommands $}}
+  {{if (Macro "IsFunctionExported" $f)}}
+    __attribute__((visibility("default")))
+    VKAPI_ATTR {{Node "Type" $f.Return}} {{$f.Name}}({{Macro "Parameters" $f}}) {
+      {{     if eq $f.Name "vkGetInstanceProcAddr"}}
+        {{Macro "api.C++.InterceptInstanceProcAddr" $}}
+      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
+        {{Macro "api.C++.InterceptDeviceProcAddr" $}}
+      {{end}}
+
+      {{Macro "api.C++.Dispatch" $f}}
+    }
+    ¶
+  {{end}}
+{{end}}

+// clang-format on
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  driver_gen.h
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver_gen.h"}}
+{{Macro "Copyright"}}

+// WARNING: This file is generated. See ../README.md for instructions.

+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H

+#include <bitset>
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_android_native_buffer.h>

+namespace vulkan {«
+namespace driver {«

+{{Macro "driver.C++.DefineProcHookType"}}

+struct InstanceDriverTable {
+  // clang-format off
+  {{range $f := AllCommands $}}
+    {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
+      {{Macro "C++.DeclareTableEntry" $f}};
+    {{end}}
+  {{end}}
+  // clang-format on
+};

+struct DeviceDriverTable {
+  // clang-format off
+  {{range $f := AllCommands $}}
+    {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
+      {{Macro "C++.DeclareTableEntry" $f}};
+    {{end}}
+  {{end}}
+  // clang-format on
+};

+const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);

+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);
+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions);

+»} // namespace driver
+»} // namespace vulkan

+#endif // LIBVULKAN_DRIVER_TABLE_H
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  driver_gen.cpp
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver_gen.cpp"}}
+{{Macro "Copyright"}}

+// WARNING: This file is generated. See ../README.md for instructions.

+#include <string.h>
+#include <algorithm>
+#include <log/log.h>

+#include "driver.h"

+namespace vulkan {«
+namespace driver {«

+namespace {«

+// clang-format off

+{{range $f := AllCommands $}}
+  {{Macro "driver.C++.DefineProcHookStub" $f}}
+{{end}}
+// clang-format on

+const ProcHook g_proc_hooks[] = {
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if (Macro "driver.IsIntercepted" $f)}}
+      {{     if (Macro "IsGloballyDispatched" $f)}}
+        {{Macro "driver.C++.DefineGlobalProcHook" $f}}
+      {{else if (Macro "IsInstanceDispatched" $f)}}
+        {{Macro "driver.C++.DefineInstanceProcHook" $f}}
+      {{else if (Macro "IsDeviceDispatched" $f)}}
+        {{Macro "driver.C++.DefineDeviceProcHook" $f}}
+      {{end}}
+    {{end}}
+  {{end}}
+  // clang-format on
+};

+»} // anonymous

+const ProcHook* GetProcHook(const char* name) {
+    const auto& begin = g_proc_hooks;
+    const auto& end = g_proc_hooks +
+      sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+    const auto hook = std::lower_bound(begin, end, name,
+        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+    return (hook <  end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}

+ProcHook::Extension GetProcHookExtension(const char* name) {
+  {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+  // clang-format off
+  {{range $e := $exts}}
+    if (strcmp(name, "{{$e}}") == 0) return ProcHook::{{TrimPrefix "VK_" $e}};
+  {{end}}
+  // clang-format on
+  return ProcHook::EXTENSION_UNKNOWN;
+}

+{{Macro "C++.DefineInitProcMacro" "driver"}}

+{{Macro "driver.C++.DefineInitProcExtMacro"}}

+bool InitDriverTable(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
+{
+    auto& data = GetData(instance);
+    bool success = true;
+    ¶
+    // clang-format off
+    {{range $f := AllCommands $}}
+      {{if (Macro "driver.IsInstanceDriverTableEntry" $f)}}
+        {{Macro "C++.InitProc" $f}}
+      {{end}}
+    {{end}}
+    // clang-format on
+    ¶
+    return success;
+}

+bool InitDriverTable(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT> &extensions)
+{
+    auto& data = GetData(dev);
+    bool success = true;
+    ¶
+    // clang-format off
+    {{range $f := AllCommands $}}
+      {{if (Macro "driver.IsDeviceDriverTableEntry" $f)}}
+        {{Macro "C++.InitProc" $f}}
+      {{end}}
+    {{end}}
+    // clang-format on
+    ¶
+    return success;
+}

+»} // namespace driver
+»} // namespace vulkan

+// clang-format on
+¶{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits a declaration of a dispatch/driver table entry.
+------------------------------------------------------------------------------
+*/}}
+{{define "C++.DeclareTableEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{Macro "FunctionPtrName" $}} {{Macro "BaseName" $}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits INIT_PROC macro.
+-------------------------------------------------------------------------------
+*/}}
+{{define "C++.DefineInitProcMacro"}}
+  #define UNLIKELY(expr) __builtin_expect((expr), 0)
+  ¶
+  #define INIT_PROC(obj, proc) do {                             \
+      data.{{$}}.proc = reinterpret_cast<PFN_vk ## proc>(       \
+              get_proc(obj, "vk" # proc));                      \
+      if (UNLIKELY(!data.{{$}}.proc)) {                         \
+          ALOGE("missing " # obj " proc: vk" # proc);           \
+          success = false;                                      \
+      }                                                         \
+  } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits code to invoke INIT_PROC or INIT_PROC_EXT.
+-------------------------------------------------------------------------------
+*/}}
+{{define "C++.InitProc"}}
+  {{AssertType $ "Function"}}
+
+  {{$ext := GetAnnotation $ "extension"}}
+  {{if $ext}}
+    INIT_PROC_EXT({{Macro "BaseName" $ext}}, §
+  {{else}}
+    INIT_PROC(§
+  {{end}}
+
+  {{if (Macro "IsInstanceDispatched" $)}}
+    instance, §
+  {{else}}
+    dev, §
+  {{end}}
+
+  {{Macro "BaseName" $}});
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if a function is exported and instance-dispatched.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.IsInstanceDispatchTableEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{if and (Macro "IsFunctionExported" $) (Macro "IsInstanceDispatched" $)}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if a function is exported and device-dispatched.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.IsDeviceDispatchTableEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{if and (Macro "IsFunctionExported" $) (Macro "IsDeviceDispatched" $)}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if a function is intercepted by vulkan::api.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.IsIntercepted"}}
+  {{AssertType $ "Function"}}
+
+  {{if (Macro "IsFunctionSupported" $)}}
+    {{/* Global functions cannot be dispatched at all */}}
+    {{     if (Macro "IsGloballyDispatched" $)}}true
+
+    {{/* VkPhysicalDevice functions that manage device layers */}}
+    {{else if eq $.Name "vkCreateDevice"}}true
+    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
+    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+    {{/* Destroy functions of dispatchable objects */}}
+    {{else if eq $.Name "vkDestroyInstance"}}true
+    {{else if eq $.Name "vkDestroyDevice"}}true
+
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits INIT_PROC_EXT macro for vulkan::api.
+-------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.DefineInitProcExtMacro"}}
+  // Exported extension functions may be invoked even when their extensions
+  // are disabled.  Dispatch to stubs when that happens.
+  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
+      if (extensions[driver::ProcHook::ext])                    \
+        INIT_PROC(obj, proc);                                   \
+      else                                                      \
+        data.dispatch.proc = disabled ## proc;                  \
+  } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a stub for an exported extension function.
+-------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.DefineExtensionStub"}}
+  {{AssertType $ "Function"}}
+
+  {{$ext := GetAnnotation $ "extension"}}
+  {{if and $ext (Macro "IsFunctionExported" $)}}
+    {{$ext_name := index $ext.Arguments 0}}
+
+    {{$base := (Macro "BaseName" $)}}
+    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
+
+    VKAPI_ATTR {{Node "Type" $.Return}} disabled{{$base}}({{$unnamed_params}}) {
+      ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
+      {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
+    }
+    ¶
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits code for vkGetInstanceProcAddr for function interception.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.InterceptInstanceProcAddr"}}
+  {{AssertType $ "API"}}
+
+  // global functions
+  if (!instance) {
+    {{range $f := AllCommands $}}
+      {{if (Macro "IsGloballyDispatched" $f)}}
+        if (strcmp(pName, "{{$f.Name}}") == 0) return §
+          reinterpret_cast<PFN_vkVoidFunction>(§
+            vulkan::api::{{Macro "BaseName" $f}});
+      {{end}}
+    {{end}}
+    ¶
+    ALOGE("vkGetInstanceProcAddr called with %s without instance",  pName);
+    return nullptr;
+  }
+  ¶
+  static const struct Hook {
+    const char* name;
+    PFN_vkVoidFunction proc;
+  } hooks[] = {
+    {{range $f := SortBy (AllCommands $) "FunctionName"}}
+      {{if (Macro "IsFunctionExported" $f)}}
+        {{/* hide global functions */}}
+        {{if (Macro "IsGloballyDispatched" $f)}}
+          { "{{$f.Name}}", nullptr },
+
+        {{/* redirect intercepted functions */}}
+        {{else if (Macro "api.IsIntercepted" $f)}}
+          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
+            vulkan::api::{{Macro "BaseName" $f}}) },
+
+        {{/* redirect vkGetInstanceProcAddr to itself */}}
+        {{else if eq $f.Name "vkGetInstanceProcAddr"}}
+          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
+
+        {{/* redirect device functions to themselves as a workaround for
+             layers that do not intercept in their vkGetInstanceProcAddr */}}
+        {{else if (Macro "IsDeviceDispatched" $f)}}
+          { "{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>({{$f.Name}}) },
+
+        {{end}}
+      {{end}}
+    {{end}}
+  };
+  // clang-format on
+  constexpr size_t count = sizeof(hooks) / sizeof(hooks[0]);
+  auto hook = std::lower_bound(
+    hooks, hooks + count, pName,
+    [](const Hook& h, const char* n) { return strcmp(h.name, n) < 0; });
+  if (hook <  hooks + count && strcmp(hook->name, pName) == 0) {
+    if (!hook->proc)
+      ALOGE("vkGetInstanceProcAddr called with %s with instance",  pName);
+    return hook->proc;
+  }
+  // clang-format off
+  ¶
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits code for vkGetDeviceProcAddr for function interception.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.InterceptDeviceProcAddr"}}
+  {{AssertType $ "API"}}
+
+  if (device == VK_NULL_HANDLE) {
+    ALOGE("vkGetDeviceProcAddr called with invalid device");
+    return nullptr;
+  }
+  ¶
+  static const char* const known_non_device_names[] = {
+    {{range $f := SortBy (AllCommands $) "FunctionName"}}
+      {{if (Macro "IsFunctionSupported" $f)}}
+        {{if not (Macro "IsDeviceDispatched" $f)}}
+          "{{$f.Name}}",
+        {{end}}
+      {{end}}
+    {{end}}
+  };
+  // clang-format on
+  constexpr size_t count = sizeof(known_non_device_names) /
+    sizeof(known_non_device_names[0]);
+  if (!pName ||
+      std::binary_search(
+        known_non_device_names, known_non_device_names + count, pName,
+        [](const char* a, const char* b) { return (strcmp(a, b) < 0); })) {
+    ALOGE("vkGetDeviceProcAddr called with %s", (pName) ? pName : "(null)");
+    return nullptr;
+  }
+  // clang-format off
+  ¶
+  {{range $f := AllCommands $}}
+    {{if (Macro "IsDeviceDispatched" $f)}}
+      {{     if (Macro "api.IsIntercepted" $f)}}
+        if (strcmp(pName, "{{$f.Name}}") == 0) return §
+          reinterpret_cast<PFN_vkVoidFunction>(§
+            vulkan::api::{{Macro "BaseName" $f}});
+      {{else if eq $f.Name "vkGetDeviceProcAddr"}}
+        if (strcmp(pName, "{{$f.Name}}") == 0) return §
+          reinterpret_cast<PFN_vkVoidFunction>(§
+            {{$f.Name}});
+      {{end}}
+    {{end}}
+  {{end}}
+  ¶
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits code to dispatch a function.
+------------------------------------------------------------------------------
+*/}}
+{{define "api.C++.Dispatch"}}
+  {{AssertType $ "Function"}}
+
+  {{if (Macro "api.IsIntercepted" $)}}// call into api.cpp{{end}}
+  {{if not (IsVoid $.Return.Type)}}return §{{end}}
+
+  {{if (Macro "api.IsIntercepted" $)}}
+    vulkan::api::§
+  {{else}}
+    {{$p0 := index $.CallParameters 0}}
+    vulkan::api::GetData({{$p0.Name}}).dispatch.§
+  {{end}}
+
+  {{Macro "BaseName" $}}({{Macro "Arguments" $}});
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits a list of extensions intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.InterceptedExtensions"}}
+VK_ANDROID_native_buffer
+VK_EXT_debug_report
+VK_KHR_android_surface
+VK_KHR_surface
+VK_KHR_swapchain
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if an extension is intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsExtensionIntercepted"}}
+  {{$ext_name := index $.Arguments 0}}
+  {{$filters := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+
+  {{range $f := $filters}}
+    {{if eq $ext_name $f}}true{{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if a function is intercepted by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsIntercepted"}}
+  {{AssertType $ "Function"}}
+
+  {{if (Macro "IsFunctionSupported" $)}}
+    {{/* Create functions of dispatchable objects */}}
+    {{     if eq $.Name "vkCreateInstance"}}true
+    {{else if eq $.Name "vkCreateDevice"}}true
+    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+    {{else if eq $.Name "vkGetDeviceQueue"}}true
+    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
+
+    {{/* Destroy functions of dispatchable objects */}}
+    {{else if eq $.Name "vkDestroyInstance"}}true
+    {{else if eq $.Name "vkDestroyDevice"}}true
+
+    {{/* Enumeration of extensions */}}
+    {{else if eq $.Name "vkEnumerateInstanceExtensionProperties"}}true
+    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
+    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
+
+    {{end}}
+
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      {{Macro "driver.IsExtensionIntercepted" $ext}}
+    {{end}}
+
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if a function needs a ProcHook stub.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.NeedProcHookStub"}}
+  {{AssertType $ "Function"}}
+
+  {{if and (Macro "driver.IsIntercepted" $) (Macro "IsDeviceDispatched" $)}}
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      {{if not (Macro "IsExtensionInternal" $ext)}}true{{end}}
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits definition of struct ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineProcHookType"}}
+  struct ProcHook {
+      enum Type {
+        GLOBAL,
+        INSTANCE,
+        DEVICE,
+      };
+
+      enum Extension {
+        {{$exts := Strings (Macro "driver.InterceptedExtensions") | SplitOn "\n"}}
+        {{range $e := $exts}}
+          {{TrimPrefix "VK_" $e}},
+        {{end}}
+        ¶
+        EXTENSION_CORE, // valid bit
+        EXTENSION_COUNT,
+        EXTENSION_UNKNOWN,
+      };
+      ¶
+      const char* name;
+      Type type;
+      Extension extension;
+      ¶
+      PFN_vkVoidFunction proc;
+      PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
+  };
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits INIT_PROC_EXT macro for vulkan::driver.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineInitProcExtMacro"}}
+  #define INIT_PROC_EXT(ext, obj, proc) do {                    \
+      if (extensions[ProcHook::ext])                            \
+        INIT_PROC(obj, proc);                                   \
+  } while(0)
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a stub for ProcHook::checked_proc.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineProcHookStub"}}
+  {{AssertType $ "Function"}}
+
+  {{if (Macro "driver.NeedProcHookStub" $)}}
+    {{$ext := GetAnnotation $ "extension"}}
+    {{$ext_name := index $ext.Arguments 0}}
+
+    {{$base := (Macro "BaseName" $)}}
+    {{$unnamed_params := (ForEach $.CallParameters "ParameterType" | JoinWith ", ")}}
+
+    VKAPI_ATTR {{Node "Type" $.Return}} checked{{$base}}({{Macro "Parameters" $}}) {
+      {{$p0 := index $.CallParameters 0}}
+      {{$ext_hook := Strings ("ProcHook::") (Macro "BaseName" $ext)}}
+
+      if (GetData({{$p0.Name}}).hook_extensions[{{$ext_hook}}]) {
+        {{if not (IsVoid $.Return.Type)}}return §{{end}}
+        {{$base}}({{Macro "Arguments" $}});
+      } else {
+        ALOGE("{{$ext_name}} not enabled. {{$.Name}} not executed.");
+        {{if not (IsVoid $.Return.Type)}}return VK_SUCCESS;{{end}}
+      }
+    }
+    ¶
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits definition of a global ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineGlobalProcHook"}}
+  {{AssertType $ "Function"}}
+
+  {{$base := (Macro "BaseName" $)}}
+
+  {{$ext := GetAnnotation $ "extension"}}
+  {{if $ext}}
+    {{Error "invalid global extension"}}
+  {{end}}
+
+  {
+    "{{$.Name}}",
+    ProcHook::GLOBAL,
+    ProcHook::EXTENSION_CORE,
+    reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+    nullptr,
+  },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits definition of an instance ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineInstanceProcHook"}}
+  {{AssertType $ "Function"}}
+
+  {{$base := (Macro "BaseName" $)}}
+
+  {
+    "{{$.Name}}",
+    ProcHook::INSTANCE,
+
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      ProcHook::{{Macro "BaseName" $ext}},
+
+      {{if (Macro "IsExtensionInternal" $ext)}}
+        nullptr,
+        nullptr,
+      {{else}}
+        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+        nullptr,
+      {{end}}
+    {{else}}
+      ProcHook::EXTENSION_CORE,
+      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+      nullptr,
+    {{end}}
+  },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits definition of a device ProcHook.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.C++.DefineDeviceProcHook"}}
+  {{AssertType $ "Function"}}
+
+  {{$base := (Macro "BaseName" $)}}
+
+  {
+    "{{$.Name}}",
+    ProcHook::DEVICE,
+
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      ProcHook::{{Macro "BaseName" $ext}},
+
+      {{if (Macro "IsExtensionInternal" $ext)}}
+        nullptr,
+        nullptr,
+      {{else}}
+        reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+        reinterpret_cast<PFN_vkVoidFunction>(checked{{$base}}),
+      {{end}}
+    {{else}}
+      ProcHook::EXTENSION_CORE,
+      reinterpret_cast<PFN_vkVoidFunction>({{$base}}),
+      nullptr,
+    {{end}}
+  },
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits true if a function is needed by vulkan::driver.
+-------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsDriverTableEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{if (Macro "IsFunctionSupported" $)}}
+    {{/* Create functions of dispatchable objects */}}
+    {{     if eq $.Name "vkCreateDevice"}}true
+    {{else if eq $.Name "vkGetDeviceQueue"}}true
+    {{else if eq $.Name "vkAllocateCommandBuffers"}}true
+
+    {{/* Destroy functions of dispatchable objects */}}
+    {{else if eq $.Name "vkDestroyInstance"}}true
+    {{else if eq $.Name "vkDestroyDevice"}}true
+
+    {{else if eq $.Name "vkEnumerateDeviceLayerProperties"}}true
+
+    {{/* Enumeration of extensions */}}
+    {{else if eq $.Name "vkEnumerateDeviceExtensionProperties"}}true
+
+    {{/* We cache physical devices in loader.cpp */}}
+    {{else if eq $.Name "vkEnumeratePhysicalDevices"}}true
+
+    {{else if eq $.Name "vkGetInstanceProcAddr"}}true
+    {{else if eq $.Name "vkGetDeviceProcAddr"}}true
+
+    {{/* VK_KHR_swapchain->VK_ANDROID_native_buffer translation */}}
+    {{else if eq $.Name "vkCreateImage"}}true
+    {{else if eq $.Name "vkDestroyImage"}}true
+
+    {{end}}
+
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      {{$ext_name := index $ext.Arguments 0}}
+      {{     if eq $ext_name "VK_ANDROID_native_buffer"}}true
+      {{else if eq $ext_name "VK_EXT_debug_report"}}true
+      {{end}}
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if an instance-dispatched function is needed by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsInstanceDriverTableEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsInstanceDispatched" $)}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits true if a device-dispatched function is needed by vulkan::driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "driver.IsDeviceDriverTableEntry"}}
+  {{AssertType $ "Function"}}
+
+  {{if and (Macro "driver.IsDriverTableEntry" $) (Macro "IsDeviceDispatched" $)}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a function/extension name without the "vk"/"VK_" prefix.
+-------------------------------------------------------------------------------
+*/}}
+{{define "BaseName"}}
+  {{     if IsFunction $}}{{TrimPrefix "vk" $.Name}}
+  {{else if eq $.Name "extension"}}{{TrimPrefix "VK_" (index $.Arguments 0)}}
+  {{else}}{{Error "invalid use of BaseName"}}
+  {{end}}
+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a comma-separated list of C parameter names for the given command.
+-------------------------------------------------------------------------------
+*/}}
+{{define "Arguments"}}
+  {{AssertType $ "Function"}}
+
+  {{ForEach $.CallParameters "ParameterName" | JoinWith ", "}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+*/}}
+{{define "IsGloballyDispatched"}}
+  {{AssertType $ "Function"}}
+  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Global")}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emit "true" for supported functions that undergo table dispatch. Only global
+  functions and functions handled in the loader top without calling into
+  lower layers are not dispatched.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsInstanceDispatched"}}
+  {{AssertType $ "Function"}}
+  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Instance")}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emit "true" for supported functions that can have device-specific dispatch.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsDeviceDispatched"}}
+  {{AssertType $ "Function"}}
+  {{if and (Macro "IsFunctionSupported" $) (eq (Macro "Vtbl" $) "Device")}}
+    true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emit "true" if a function is core or from a supportable extension.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsFunctionSupported"}}
+  {{AssertType $ "Function"}}
+  {{if not (GetAnnotation $ "pfn")}}
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if not $ext}}true
+    {{else if not (Macro "IsExtensionBlacklisted" $ext)}}true
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Decides whether a function should be exported from the Android Vulkan
+  library. Functions in the core API and in loader extensions are exported.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsFunctionExported"}}
+  {{AssertType $ "Function"}}
+
+  {{if (Macro "IsFunctionSupported" $)}}
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      {{Macro "IsExtensionExported" $ext}}
+    {{else}}
+      true
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emit "true" if an extension is unsupportable on Android.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionBlacklisted"}}
+  {{$ext := index $.Arguments 0}}
+  {{     if eq $ext "VK_KHR_display"}}true
+  {{else if eq $ext "VK_KHR_display_swapchain"}}true
+  {{else if eq $ext "VK_KHR_xlib_surface"}}true
+  {{else if eq $ext "VK_KHR_xcb_surface"}}true
+  {{else if eq $ext "VK_KHR_wayland_surface"}}true
+  {{else if eq $ext "VK_KHR_mir_surface"}}true
+  {{else if eq $ext "VK_KHR_win32_surface"}}true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Reports whether an extension is implemented entirely by the loader,
+  so drivers should not enumerate it.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionExported"}}
+  {{$ext := index $.Arguments 0}}
+  {{     if eq $ext "VK_KHR_surface"}}true
+  {{else if eq $ext "VK_KHR_swapchain"}}true
+  {{else if eq $ext "VK_KHR_android_surface"}}true
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Reports whether an extension is internal to the loader and drivers,
+  so the loader should not enumerate it.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsExtensionInternal"}}
+  {{$ext := index $.Arguments 0}}
+  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
+  {{end}}
+{{end}}
diff --git a/vulkan/libvulkan/debug_report.cpp b/vulkan/libvulkan/debug_report.cpp
new file mode 100644
index 0000000..c4a1174
--- /dev/null
+++ b/vulkan/libvulkan/debug_report.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.h"
+
+namespace vulkan {
+namespace driver {
+
+VkResult DebugReportCallbackList::CreateCallback(
+    VkInstance instance,
+    const VkDebugReportCallbackCreateInfoEXT* create_info,
+    const VkAllocationCallbacks* allocator,
+    VkDebugReportCallbackEXT* callback) {
+    VkDebugReportCallbackEXT driver_callback = VK_NULL_HANDLE;
+
+    if (GetData(instance).driver.CreateDebugReportCallbackEXT) {
+        VkResult result = GetData(instance).driver.CreateDebugReportCallbackEXT(
+            instance, create_info, allocator, &driver_callback);
+        if (result != VK_SUCCESS)
+            return result;
+    }
+
+    const VkAllocationCallbacks* alloc =
+        allocator ? allocator : &GetData(instance).allocator;
+    void* mem =
+        alloc->pfnAllocation(alloc->pUserData, sizeof(Node), alignof(Node),
+                             VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (!mem) {
+        if (GetData(instance).driver.DestroyDebugReportCallbackEXT) {
+            GetData(instance).driver.DestroyDebugReportCallbackEXT(
+                instance, driver_callback, allocator);
+        }
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+
+    std::lock_guard<decltype(rwmutex_)> lock(rwmutex_);
+    head_.next =
+        new (mem) Node{head_.next, create_info->flags, create_info->pfnCallback,
+                       create_info->pUserData, driver_callback};
+    *callback =
+        VkDebugReportCallbackEXT(reinterpret_cast<uintptr_t>(head_.next));
+    return VK_SUCCESS;
+}
+
+void DebugReportCallbackList::DestroyCallback(
+    VkInstance instance,
+    VkDebugReportCallbackEXT callback,
+    const VkAllocationCallbacks* allocator) {
+    Node* node = reinterpret_cast<Node*>(uintptr_t(callback));
+    std::unique_lock<decltype(rwmutex_)> lock(rwmutex_);
+    Node* prev = &head_;
+    while (prev && prev->next != node)
+        prev = prev->next;
+    prev->next = node->next;
+    lock.unlock();
+
+    if (GetData(instance).driver.DestroyDebugReportCallbackEXT) {
+        GetData(instance).driver.DestroyDebugReportCallbackEXT(
+            instance, node->driver_callback, allocator);
+    }
+
+    const VkAllocationCallbacks* alloc =
+        allocator ? allocator : &GetData(instance).allocator;
+    alloc->pfnFree(alloc->pUserData, node);
+}
+
+void DebugReportCallbackList::Message(VkDebugReportFlagsEXT flags,
+                                      VkDebugReportObjectTypeEXT object_type,
+                                      uint64_t object,
+                                      size_t location,
+                                      int32_t message_code,
+                                      const char* layer_prefix,
+                                      const char* message) {
+    std::shared_lock<decltype(rwmutex_)> lock(rwmutex_);
+    Node* node = &head_;
+    while ((node = node->next)) {
+        if ((node->flags & flags) != 0) {
+            node->callback(flags, object_type, object, location, message_code,
+                           layer_prefix, message, node->data);
+        }
+    }
+}
+
+VkResult CreateDebugReportCallbackEXT(
+    VkInstance instance,
+    const VkDebugReportCallbackCreateInfoEXT* create_info,
+    const VkAllocationCallbacks* allocator,
+    VkDebugReportCallbackEXT* callback) {
+    return GetData(instance).debug_report_callbacks.CreateCallback(
+        instance, create_info, allocator, callback);
+}
+
+void DestroyDebugReportCallbackEXT(VkInstance instance,
+                                   VkDebugReportCallbackEXT callback,
+                                   const VkAllocationCallbacks* allocator) {
+    if (callback)
+        GetData(instance).debug_report_callbacks.DestroyCallback(
+            instance, callback, allocator);
+}
+
+void DebugReportMessageEXT(VkInstance instance,
+                           VkDebugReportFlagsEXT flags,
+                           VkDebugReportObjectTypeEXT object_type,
+                           uint64_t object,
+                           size_t location,
+                           int32_t message_code,
+                           const char* layer_prefix,
+                           const char* message) {
+    if (GetData(instance).driver.DebugReportMessageEXT) {
+        GetData(instance).driver.DebugReportMessageEXT(
+            instance, flags, object_type, object, location, message_code,
+            layer_prefix, message);
+    }
+    GetData(instance).debug_report_callbacks.Message(flags, object_type, object,
+                                                     location, message_code,
+                                                     layer_prefix, message);
+}
+
+}  // namespace driver
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/debug_report.h b/vulkan/libvulkan/debug_report.h
new file mode 100644
index 0000000..72b1887
--- /dev/null
+++ b/vulkan/libvulkan/debug_report.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LIBVULKAN_DEBUG_REPORT_H
+#define LIBVULKAN_DEBUG_REPORT_H 1
+
+#include <vulkan/vulkan.h>
+#include <shared_mutex>
+
+namespace vulkan {
+namespace driver {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+// clang-format on
+
+class DebugReportCallbackList {
+   public:
+    DebugReportCallbackList()
+        : head_{nullptr, 0, nullptr, nullptr, VK_NULL_HANDLE} {}
+    DebugReportCallbackList(const DebugReportCallbackList&) = delete;
+    DebugReportCallbackList& operator=(const DebugReportCallbackList&) = delete;
+    ~DebugReportCallbackList() = default;
+
+    VkResult CreateCallback(
+        VkInstance instance,
+        const VkDebugReportCallbackCreateInfoEXT* create_info,
+        const VkAllocationCallbacks* allocator,
+        VkDebugReportCallbackEXT* callback);
+    void DestroyCallback(VkInstance instance,
+                         VkDebugReportCallbackEXT callback,
+                         const VkAllocationCallbacks* allocator);
+    void Message(VkDebugReportFlagsEXT flags,
+                 VkDebugReportObjectTypeEXT object_type,
+                 uint64_t object,
+                 size_t location,
+                 int32_t message_code,
+                 const char* layer_prefix,
+                 const char* message);
+
+   private:
+    struct Node {
+        Node* next;
+        VkDebugReportFlagsEXT flags;
+        PFN_vkDebugReportCallbackEXT callback;
+        void* data;
+        VkDebugReportCallbackEXT driver_callback;
+    };
+
+    // TODO(jessehall): replace with std::shared_mutex when available in libc++
+    std::shared_timed_mutex rwmutex_;
+    Node head_;
+};
+
+}  // namespace driver
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_DEBUG_REPORT_H
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
new file mode 100644
index 0000000..b02f5b4
--- /dev/null
+++ b/vulkan/libvulkan/driver.cpp
@@ -0,0 +1,777 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <array>
+#include <new>
+#include <malloc.h>
+#include <sys/prctl.h>
+
+#include "driver.h"
+#include "stubhal.h"
+
+// #define ENABLE_ALLOC_CALLSTACKS 1
+#if ENABLE_ALLOC_CALLSTACKS
+#include <utils/CallStack.h>
+#define ALOGD_CALLSTACK(...)                             \
+    do {                                                 \
+        ALOGD(__VA_ARGS__);                              \
+        android::CallStack callstack;                    \
+        callstack.update();                              \
+        callstack.log(LOG_TAG, ANDROID_LOG_DEBUG, "  "); \
+    } while (false)
+#else
+#define ALOGD_CALLSTACK(...) \
+    do {                     \
+    } while (false)
+#endif
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+class CreateInfoWrapper {
+   public:
+    CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
+                      const VkInstanceCreateInfo& create_info,
+                      const VkAllocationCallbacks& allocator);
+    CreateInfoWrapper(VkPhysicalDevice physical_dev,
+                      const VkDeviceCreateInfo& create_info,
+                      const VkAllocationCallbacks& allocator);
+    ~CreateInfoWrapper();
+
+    VkResult Validate();
+
+    const std::bitset<ProcHook::EXTENSION_COUNT>& GetHookExtensions() const;
+    const std::bitset<ProcHook::EXTENSION_COUNT>& GetHalExtensions() const;
+
+    explicit operator const VkInstanceCreateInfo*() const;
+    explicit operator const VkDeviceCreateInfo*() const;
+
+   private:
+    struct ExtensionFilter {
+        VkExtensionProperties* exts;
+        uint32_t ext_count;
+
+        const char** names;
+        uint32_t name_count;
+    };
+
+    VkResult SanitizePNext();
+
+    VkResult SanitizeLayers();
+    VkResult SanitizeExtensions();
+
+    VkResult QueryExtensionCount(uint32_t& count) const;
+    VkResult EnumerateExtensions(uint32_t& count,
+                                 VkExtensionProperties* props) const;
+    VkResult InitExtensionFilter();
+    void FilterExtension(const char* name);
+
+    const bool is_instance_;
+    const VkAllocationCallbacks& allocator_;
+
+    union {
+        const hwvulkan_device_t* hw_dev_;
+        VkPhysicalDevice physical_dev_;
+    };
+
+    union {
+        VkInstanceCreateInfo instance_info_;
+        VkDeviceCreateInfo dev_info_;
+    };
+
+    ExtensionFilter extension_filter_;
+
+    std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions_;
+    std::bitset<ProcHook::EXTENSION_COUNT> hal_extensions_;
+};
+
+CreateInfoWrapper::CreateInfoWrapper(const hwvulkan_device_t* hw_dev,
+                                     const VkInstanceCreateInfo& create_info,
+                                     const VkAllocationCallbacks& allocator)
+    : is_instance_(true),
+      allocator_(allocator),
+      hw_dev_(hw_dev),
+      instance_info_(create_info),
+      extension_filter_() {
+    hook_extensions_.set(ProcHook::EXTENSION_CORE);
+    hal_extensions_.set(ProcHook::EXTENSION_CORE);
+}
+
+CreateInfoWrapper::CreateInfoWrapper(VkPhysicalDevice physical_dev,
+                                     const VkDeviceCreateInfo& create_info,
+                                     const VkAllocationCallbacks& allocator)
+    : is_instance_(false),
+      allocator_(allocator),
+      physical_dev_(physical_dev),
+      dev_info_(create_info),
+      extension_filter_() {
+    hook_extensions_.set(ProcHook::EXTENSION_CORE);
+    hal_extensions_.set(ProcHook::EXTENSION_CORE);
+}
+
+CreateInfoWrapper::~CreateInfoWrapper() {
+    allocator_.pfnFree(allocator_.pUserData, extension_filter_.exts);
+    allocator_.pfnFree(allocator_.pUserData, extension_filter_.names);
+}
+
+VkResult CreateInfoWrapper::Validate() {
+    VkResult result = SanitizePNext();
+    if (result == VK_SUCCESS)
+        result = SanitizeLayers();
+    if (result == VK_SUCCESS)
+        result = SanitizeExtensions();
+
+    return result;
+}
+
+const std::bitset<ProcHook::EXTENSION_COUNT>&
+CreateInfoWrapper::GetHookExtensions() const {
+    return hook_extensions_;
+}
+
+const std::bitset<ProcHook::EXTENSION_COUNT>&
+CreateInfoWrapper::GetHalExtensions() const {
+    return hal_extensions_;
+}
+
+CreateInfoWrapper::operator const VkInstanceCreateInfo*() const {
+    return &instance_info_;
+}
+
+CreateInfoWrapper::operator const VkDeviceCreateInfo*() const {
+    return &dev_info_;
+}
+
+VkResult CreateInfoWrapper::SanitizePNext() {
+    const struct StructHeader {
+        VkStructureType type;
+        const void* next;
+    } * header;
+
+    if (is_instance_) {
+        header = reinterpret_cast<const StructHeader*>(instance_info_.pNext);
+
+        // skip leading VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFOs
+        while (header &&
+               header->type == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO)
+            header = reinterpret_cast<const StructHeader*>(header->next);
+
+        instance_info_.pNext = header;
+    } else {
+        header = reinterpret_cast<const StructHeader*>(dev_info_.pNext);
+
+        // skip leading VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFOs
+        while (header &&
+               header->type == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO)
+            header = reinterpret_cast<const StructHeader*>(header->next);
+
+        dev_info_.pNext = header;
+    }
+
+    return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::SanitizeLayers() {
+    auto& layer_names = (is_instance_) ? instance_info_.ppEnabledLayerNames
+                                       : dev_info_.ppEnabledLayerNames;
+    auto& layer_count = (is_instance_) ? instance_info_.enabledLayerCount
+                                       : dev_info_.enabledLayerCount;
+
+    // remove all layers
+    layer_names = nullptr;
+    layer_count = 0;
+
+    return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::SanitizeExtensions() {
+    auto& ext_names = (is_instance_) ? instance_info_.ppEnabledExtensionNames
+                                     : dev_info_.ppEnabledExtensionNames;
+    auto& ext_count = (is_instance_) ? instance_info_.enabledExtensionCount
+                                     : dev_info_.enabledExtensionCount;
+    if (!ext_count)
+        return VK_SUCCESS;
+
+    VkResult result = InitExtensionFilter();
+    if (result != VK_SUCCESS)
+        return result;
+
+    for (uint32_t i = 0; i < ext_count; i++)
+        FilterExtension(ext_names[i]);
+
+    ext_names = extension_filter_.names;
+    ext_count = extension_filter_.name_count;
+
+    return VK_SUCCESS;
+}
+
+VkResult CreateInfoWrapper::QueryExtensionCount(uint32_t& count) const {
+    if (is_instance_) {
+        return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
+                                                             nullptr);
+    } else {
+        const auto& driver = GetData(physical_dev_).driver;
+        return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
+                                                         &count, nullptr);
+    }
+}
+
+VkResult CreateInfoWrapper::EnumerateExtensions(
+    uint32_t& count,
+    VkExtensionProperties* props) const {
+    if (is_instance_) {
+        return hw_dev_->EnumerateInstanceExtensionProperties(nullptr, &count,
+                                                             props);
+    } else {
+        const auto& driver = GetData(physical_dev_).driver;
+        return driver.EnumerateDeviceExtensionProperties(physical_dev_, nullptr,
+                                                         &count, props);
+    }
+}
+
+VkResult CreateInfoWrapper::InitExtensionFilter() {
+    // query extension count
+    uint32_t count;
+    VkResult result = QueryExtensionCount(count);
+    if (result != VK_SUCCESS || count == 0)
+        return result;
+
+    auto& filter = extension_filter_;
+    filter.exts =
+        reinterpret_cast<VkExtensionProperties*>(allocator_.pfnAllocation(
+            allocator_.pUserData, sizeof(VkExtensionProperties) * count,
+            alignof(VkExtensionProperties),
+            VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+    if (!filter.exts)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    // enumerate extensions
+    result = EnumerateExtensions(count, filter.exts);
+    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
+        return result;
+
+    if (!count)
+        return VK_SUCCESS;
+
+    filter.ext_count = count;
+
+    // allocate name array
+    uint32_t enabled_ext_count = (is_instance_)
+                                     ? instance_info_.enabledExtensionCount
+                                     : dev_info_.enabledExtensionCount;
+    count = std::min(filter.ext_count, enabled_ext_count);
+    filter.names = reinterpret_cast<const char**>(allocator_.pfnAllocation(
+        allocator_.pUserData, sizeof(const char*) * count, alignof(const char*),
+        VK_SYSTEM_ALLOCATION_SCOPE_COMMAND));
+    if (!filter.names)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    return VK_SUCCESS;
+}
+
+void CreateInfoWrapper::FilterExtension(const char* name) {
+    auto& filter = extension_filter_;
+
+    ProcHook::Extension ext_bit = GetProcHookExtension(name);
+    if (is_instance_) {
+        switch (ext_bit) {
+            case ProcHook::KHR_android_surface:
+            case ProcHook::KHR_surface:
+                hook_extensions_.set(ext_bit);
+                // return now as these extensions do not require HAL support
+                return;
+            case ProcHook::EXT_debug_report:
+                // both we and HAL can take part in
+                hook_extensions_.set(ext_bit);
+                break;
+            case ProcHook::EXTENSION_UNKNOWN:
+                // HAL's extensions
+                break;
+            default:
+                ALOGW("Ignored invalid instance extension %s", name);
+                return;
+        }
+    } else {
+        switch (ext_bit) {
+            case ProcHook::KHR_swapchain:
+                // map VK_KHR_swapchain to VK_ANDROID_native_buffer
+                name = VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME;
+                ext_bit = ProcHook::ANDROID_native_buffer;
+                break;
+            case ProcHook::EXTENSION_UNKNOWN:
+                // HAL's extensions
+                break;
+            default:
+                ALOGW("Ignored invalid device extension %s", name);
+                return;
+        }
+    }
+
+    for (uint32_t i = 0; i < filter.ext_count; i++) {
+        const VkExtensionProperties& props = filter.exts[i];
+        // ignore unknown extensions
+        if (strcmp(name, props.extensionName) != 0)
+            continue;
+
+        filter.names[filter.name_count++] = name;
+        if (ext_bit != ProcHook::EXTENSION_UNKNOWN) {
+            if (ext_bit == ProcHook::ANDROID_native_buffer)
+                hook_extensions_.set(ProcHook::KHR_swapchain);
+
+            hal_extensions_.set(ext_bit);
+        }
+
+        break;
+    }
+}
+
+const hwvulkan_device_t* g_hwdevice = nullptr;
+
+VKAPI_ATTR void* DefaultAllocate(void*,
+                                 size_t size,
+                                 size_t alignment,
+                                 VkSystemAllocationScope) {
+    void* ptr = nullptr;
+    // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+    // additionally requires that it be at least sizeof(void*).
+    int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+    ALOGD_CALLSTACK("Allocate: size=%zu align=%zu => (%d) %p", size, alignment,
+                    ret, ptr);
+    return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+                                   void* ptr,
+                                   size_t size,
+                                   size_t alignment,
+                                   VkSystemAllocationScope) {
+    if (size == 0) {
+        free(ptr);
+        return nullptr;
+    }
+
+    // TODO(jessehall): Right now we never shrink allocations; if the new
+    // request is smaller than the existing chunk, we just continue using it.
+    // Right now the loader never reallocs, so this doesn't matter. If that
+    // changes, or if this code is copied into some other project, this should
+    // probably have a heuristic to allocate-copy-free when doing so will save
+    // "enough" space.
+    size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+    if (size <= old_size)
+        return ptr;
+
+    void* new_ptr = nullptr;
+    if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+        return nullptr;
+    if (ptr) {
+        memcpy(new_ptr, ptr, std::min(old_size, size));
+        free(ptr);
+    }
+    return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+    ALOGD_CALLSTACK("Free: %p", ptr);
+    free(ptr);
+}
+
+InstanceData* AllocateInstanceData(const VkAllocationCallbacks& allocator) {
+    void* data_mem = allocator.pfnAllocation(
+        allocator.pUserData, sizeof(InstanceData), alignof(InstanceData),
+        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+    if (!data_mem)
+        return nullptr;
+
+    return new (data_mem) InstanceData(allocator);
+}
+
+void FreeInstanceData(InstanceData* data,
+                      const VkAllocationCallbacks& allocator) {
+    data->~InstanceData();
+    allocator.pfnFree(allocator.pUserData, data);
+}
+
+DeviceData* AllocateDeviceData(const VkAllocationCallbacks& allocator) {
+    void* data_mem = allocator.pfnAllocation(
+        allocator.pUserData, sizeof(DeviceData), alignof(DeviceData),
+        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+    if (!data_mem)
+        return nullptr;
+
+    return new (data_mem) DeviceData(allocator);
+}
+
+void FreeDeviceData(DeviceData* data, const VkAllocationCallbacks& allocator) {
+    data->~DeviceData();
+    allocator.pfnFree(allocator.pUserData, data);
+}
+
+}  // anonymous namespace
+
+bool Debuggable() {
+    return (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) >= 0);
+}
+
+bool OpenHAL() {
+    ALOG_ASSERT(!g_hwdevice, "OpenHAL called more than once");
+
+    // Use a stub device unless we successfully open a real HAL device.
+    g_hwdevice = &stubhal::kDevice;
+
+    const hwvulkan_module_t* module;
+    int result =
+        hw_get_module("vulkan", reinterpret_cast<const hw_module_t**>(&module));
+    if (result != 0) {
+        ALOGV("no Vulkan HAL present, using stub HAL");
+        return true;
+    }
+
+    hwvulkan_device_t* device;
+    result =
+        module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
+                                     reinterpret_cast<hw_device_t**>(&device));
+    if (result != 0) {
+        // Any device with a Vulkan HAL should be able to open the device.
+        ALOGE("failed to open Vulkan HAL device: %s (%d)", strerror(-result),
+              result);
+        return false;
+    }
+
+    g_hwdevice = device;
+
+    return true;
+}
+
+const VkAllocationCallbacks& GetDefaultAllocator() {
+    static const VkAllocationCallbacks kDefaultAllocCallbacks = {
+        .pUserData = nullptr,
+        .pfnAllocation = DefaultAllocate,
+        .pfnReallocation = DefaultReallocate,
+        .pfnFree = DefaultFree,
+    };
+
+    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;
+
+        // v0 layers expect
+        //
+        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
+        //
+        // to work.
+        if (strcmp(pName, "vkCreateDevice") == 0)
+            return hook->proc;
+
+        ALOGE(
+            "Invalid use of vkGetInstanceProcAddr to query %s without an "
+            "instance",
+            pName);
+
+        return nullptr;
+    }
+
+    PFN_vkVoidFunction proc;
+
+    switch (hook->type) {
+        case ProcHook::INSTANCE:
+            proc = (GetData(instance).hook_extensions[hook->extension])
+                       ? hook->proc
+                       : nullptr;
+            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).driver.GetDeviceProcAddr(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
+                                                              : nullptr;
+}
+
+VkResult EnumerateInstanceExtensionProperties(
+    const char* pLayerName,
+    uint32_t* pPropertyCount,
+    VkExtensionProperties* pProperties) {
+    static const std::array<VkExtensionProperties, 2> loader_extensions = {{
+        // WSI extensions
+        {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_SURFACE_SPEC_VERSION},
+        {VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
+         VK_KHR_ANDROID_SURFACE_SPEC_VERSION},
+    }};
+
+    // enumerate our extensions first
+    if (!pLayerName && pProperties) {
+        uint32_t count = std::min(
+            *pPropertyCount, static_cast<uint32_t>(loader_extensions.size()));
+
+        std::copy_n(loader_extensions.begin(), count, pProperties);
+
+        if (count < loader_extensions.size()) {
+            *pPropertyCount = count;
+            return VK_INCOMPLETE;
+        }
+
+        pProperties += count;
+        *pPropertyCount -= count;
+    }
+
+    VkResult result = g_hwdevice->EnumerateInstanceExtensionProperties(
+        pLayerName, pPropertyCount, pProperties);
+
+    if (!pLayerName && (result == VK_SUCCESS || result == VK_INCOMPLETE))
+        *pPropertyCount += loader_extensions.size();
+
+    return result;
+}
+
+VkResult EnumerateDeviceExtensionProperties(
+    VkPhysicalDevice physicalDevice,
+    const char* pLayerName,
+    uint32_t* pPropertyCount,
+    VkExtensionProperties* pProperties) {
+    const InstanceData& data = GetData(physicalDevice);
+
+    VkResult result = data.driver.EnumerateDeviceExtensionProperties(
+        physicalDevice, pLayerName, pPropertyCount, pProperties);
+    if (result != VK_SUCCESS && result != VK_INCOMPLETE)
+        return result;
+
+    if (!pProperties)
+        return result;
+
+    // map VK_ANDROID_native_buffer to VK_KHR_swapchain
+    for (uint32_t i = 0; i < *pPropertyCount; i++) {
+        auto& prop = pProperties[i];
+
+        if (strcmp(prop.extensionName,
+                   VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) != 0)
+            continue;
+
+        memcpy(prop.extensionName, VK_KHR_SWAPCHAIN_EXTENSION_NAME,
+               sizeof(VK_KHR_SWAPCHAIN_EXTENSION_NAME));
+        prop.specVersion = VK_KHR_SWAPCHAIN_SPEC_VERSION;
+    }
+
+    return result;
+}
+
+VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo,
+                        const VkAllocationCallbacks* pAllocator,
+                        VkInstance* pInstance) {
+    const VkAllocationCallbacks& data_allocator =
+        (pAllocator) ? *pAllocator : GetDefaultAllocator();
+
+    CreateInfoWrapper wrapper(g_hwdevice, *pCreateInfo, data_allocator);
+    VkResult result = wrapper.Validate();
+    if (result != VK_SUCCESS)
+        return result;
+
+    InstanceData* data = AllocateInstanceData(data_allocator);
+    if (!data)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    data->hook_extensions |= wrapper.GetHookExtensions();
+
+    // call into the driver
+    VkInstance instance;
+    result = g_hwdevice->CreateInstance(
+        static_cast<const VkInstanceCreateInfo*>(wrapper), pAllocator,
+        &instance);
+    if (result != VK_SUCCESS) {
+        FreeInstanceData(data, data_allocator);
+        return result;
+    }
+
+    // initialize InstanceDriverTable
+    if (!SetData(instance, *data) ||
+        !InitDriverTable(instance, g_hwdevice->GetInstanceProcAddr,
+                         wrapper.GetHalExtensions())) {
+        data->driver.DestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(
+            g_hwdevice->GetInstanceProcAddr(instance, "vkDestroyInstance"));
+        if (data->driver.DestroyInstance)
+            data->driver.DestroyInstance(instance, pAllocator);
+
+        FreeInstanceData(data, data_allocator);
+
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
+    data->get_device_proc_addr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+        g_hwdevice->GetInstanceProcAddr(instance, "vkGetDeviceProcAddr"));
+    if (!data->get_device_proc_addr) {
+        data->driver.DestroyInstance(instance, pAllocator);
+        FreeInstanceData(data, data_allocator);
+
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
+    *pInstance = instance;
+
+    return VK_SUCCESS;
+}
+
+void DestroyInstance(VkInstance instance,
+                     const VkAllocationCallbacks* pAllocator) {
+    InstanceData& data = GetData(instance);
+    data.driver.DestroyInstance(instance, pAllocator);
+
+    VkAllocationCallbacks local_allocator;
+    if (!pAllocator) {
+        local_allocator = data.allocator;
+        pAllocator = &local_allocator;
+    }
+
+    FreeInstanceData(&data, *pAllocator);
+}
+
+VkResult CreateDevice(VkPhysicalDevice physicalDevice,
+                      const VkDeviceCreateInfo* pCreateInfo,
+                      const VkAllocationCallbacks* pAllocator,
+                      VkDevice* pDevice) {
+    const InstanceData& instance_data = GetData(physicalDevice);
+    const VkAllocationCallbacks& data_allocator =
+        (pAllocator) ? *pAllocator : instance_data.allocator;
+
+    CreateInfoWrapper wrapper(physicalDevice, *pCreateInfo, data_allocator);
+    VkResult result = wrapper.Validate();
+    if (result != VK_SUCCESS)
+        return result;
+
+    DeviceData* data = AllocateDeviceData(data_allocator);
+    if (!data)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    data->hook_extensions |= wrapper.GetHookExtensions();
+
+    // call into the driver
+    VkDevice dev;
+    result = instance_data.driver.CreateDevice(
+        physicalDevice, static_cast<const VkDeviceCreateInfo*>(wrapper),
+        pAllocator, &dev);
+    if (result != VK_SUCCESS) {
+        FreeDeviceData(data, data_allocator);
+        return result;
+    }
+
+    // initialize DeviceDriverTable
+    if (!SetData(dev, *data) ||
+        !InitDriverTable(dev, instance_data.get_device_proc_addr,
+                         wrapper.GetHalExtensions())) {
+        data->driver.DestroyDevice = reinterpret_cast<PFN_vkDestroyDevice>(
+            instance_data.get_device_proc_addr(dev, "vkDestroyDevice"));
+        if (data->driver.DestroyDevice)
+            data->driver.DestroyDevice(dev, pAllocator);
+
+        FreeDeviceData(data, data_allocator);
+
+        return VK_ERROR_INCOMPATIBLE_DRIVER;
+    }
+
+    *pDevice = dev;
+
+    return VK_SUCCESS;
+}
+
+void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
+    DeviceData& data = GetData(device);
+    data.driver.DestroyDevice(device, pAllocator);
+
+    VkAllocationCallbacks local_allocator;
+    if (!pAllocator) {
+        local_allocator = data.allocator;
+        pAllocator = &local_allocator;
+    }
+
+    FreeDeviceData(&data, *pAllocator);
+}
+
+VkResult EnumeratePhysicalDevices(VkInstance instance,
+                                  uint32_t* pPhysicalDeviceCount,
+                                  VkPhysicalDevice* pPhysicalDevices) {
+    const auto& data = GetData(instance);
+
+    VkResult result = data.driver.EnumeratePhysicalDevices(
+        instance, pPhysicalDeviceCount, pPhysicalDevices);
+    if ((result == VK_SUCCESS || result == VK_INCOMPLETE) && pPhysicalDevices) {
+        for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++)
+            SetData(pPhysicalDevices[i], data);
+    }
+
+    return result;
+}
+
+void GetDeviceQueue(VkDevice device,
+                    uint32_t queueFamilyIndex,
+                    uint32_t queueIndex,
+                    VkQueue* pQueue) {
+    const auto& data = GetData(device);
+
+    data.driver.GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
+    SetData(*pQueue, data);
+}
+
+VKAPI_ATTR VkResult
+AllocateCommandBuffers(VkDevice device,
+                       const VkCommandBufferAllocateInfo* pAllocateInfo,
+                       VkCommandBuffer* pCommandBuffers) {
+    const auto& data = GetData(device);
+
+    VkResult result = data.driver.AllocateCommandBuffers(device, pAllocateInfo,
+                                                         pCommandBuffers);
+    if (result == VK_SUCCESS) {
+        for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; i++)
+            SetData(pCommandBuffers[i], data);
+    }
+
+    return result;
+}
+
+}  // namespace driver
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/driver.h b/vulkan/libvulkan/driver.h
new file mode 100644
index 0000000..2b1f545
--- /dev/null
+++ b/vulkan/libvulkan/driver.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LIBVULKAN_DRIVER_H
+#define LIBVULKAN_DRIVER_H 1
+
+#include <inttypes.h>
+#include <bitset>
+#include <type_traits>
+#include <log/log.h>
+
+#include <vulkan/vulkan.h>
+#include <hardware/hwvulkan.h>
+
+#include "api_gen.h"
+#include "driver_gen.h"
+#include "debug_report.h"
+#include "swapchain.h"
+
+namespace vulkan {
+
+// This is here so that we can embed api::{Instance,Device}Data in
+// driver::{Instance,Device}Data to avoid pointer chasing.  They are
+// considered opaque to the driver layer.
+namespace api {
+
+struct InstanceData {
+    InstanceDispatchTable dispatch;
+
+    // LayerChain::ActiveLayer array
+    void* layers;
+    uint32_t layer_count;
+
+    // debug.vulkan.enable_callback
+    PFN_vkDestroyDebugReportCallbackEXT destroy_debug_callback;
+    VkDebugReportCallbackEXT debug_callback;
+};
+
+struct DeviceData {
+    DeviceDispatchTable dispatch;
+};
+
+}  // namespace api
+
+namespace driver {
+
+VK_DEFINE_HANDLE(InstanceDispatchable)
+VK_DEFINE_HANDLE(DeviceDispatchable)
+
+struct InstanceData {
+    InstanceData(const VkAllocationCallbacks& alloc)
+        : opaque_api_data(),
+          allocator(alloc),
+          driver(),
+          get_device_proc_addr(nullptr) {
+        hook_extensions.set(ProcHook::EXTENSION_CORE);
+    }
+
+    api::InstanceData opaque_api_data;
+
+    const VkAllocationCallbacks allocator;
+
+    std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions;
+
+    InstanceDriverTable driver;
+    PFN_vkGetDeviceProcAddr get_device_proc_addr;
+
+    DebugReportCallbackList debug_report_callbacks;
+};
+
+struct DeviceData {
+    DeviceData(const VkAllocationCallbacks& alloc)
+        : opaque_api_data(), allocator(alloc), driver() {
+        hook_extensions.set(ProcHook::EXTENSION_CORE);
+    }
+
+    api::DeviceData opaque_api_data;
+
+    const VkAllocationCallbacks allocator;
+
+    std::bitset<ProcHook::EXTENSION_COUNT> hook_extensions;
+
+    DeviceDriverTable driver;
+};
+
+bool Debuggable();
+bool OpenHAL();
+const VkAllocationCallbacks& GetDefaultAllocator();
+
+// clang-format off
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName);
+VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
+VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
+// clang-format on
+
+template <typename DispatchableType>
+void StaticAssertDispatchable(DispatchableType) {
+    static_assert(
+        std::is_same<DispatchableType, VkInstance>::value ||
+            std::is_same<DispatchableType, VkPhysicalDevice>::value ||
+            std::is_same<DispatchableType, VkDevice>::value ||
+            std::is_same<DispatchableType, InstanceDispatchable>::value ||
+            std::is_same<DispatchableType, VkQueue>::value ||
+            std::is_same<DispatchableType, VkCommandBuffer>::value ||
+            std::is_same<DispatchableType, DeviceDispatchable>::value,
+        "unrecognized dispatchable type");
+}
+
+template <typename DispatchableType>
+bool SetDataInternal(DispatchableType dispatchable, const void* data) {
+    StaticAssertDispatchable(dispatchable);
+
+    hwvulkan_dispatch_t* dispatch =
+        reinterpret_cast<hwvulkan_dispatch_t*>(dispatchable);
+    // must be magic or already set
+    if (dispatch->magic != HWVULKAN_DISPATCH_MAGIC && dispatch->vtbl != data) {
+        ALOGE("invalid dispatchable object magic 0x%" PRIxPTR, dispatch->magic);
+        return false;
+    }
+
+    dispatch->vtbl = data;
+
+    return true;
+}
+
+template <typename DispatchableType>
+void* GetDataInternal(DispatchableType dispatchable) {
+    StaticAssertDispatchable(dispatchable);
+
+    const hwvulkan_dispatch_t* dispatch =
+        reinterpret_cast<const hwvulkan_dispatch_t*>(dispatchable);
+
+    return const_cast<void*>(dispatch->vtbl);
+}
+
+inline bool SetData(VkInstance instance, const InstanceData& data) {
+    return SetDataInternal(instance, &data);
+}
+
+inline bool SetData(VkPhysicalDevice physical_dev, const InstanceData& data) {
+    return SetDataInternal(physical_dev, &data);
+}
+
+inline bool SetData(InstanceDispatchable dispatchable,
+                    const InstanceData& data) {
+    return SetDataInternal(dispatchable, &data);
+}
+
+inline bool SetData(VkDevice dev, const DeviceData& data) {
+    return SetDataInternal(dev, &data);
+}
+
+inline bool SetData(VkQueue queue, const DeviceData& data) {
+    return SetDataInternal(queue, &data);
+}
+
+inline bool SetData(VkCommandBuffer cmd, const DeviceData& data) {
+    return SetDataInternal(cmd, &data);
+}
+
+inline bool SetData(DeviceDispatchable dispatchable, const DeviceData& data) {
+    return SetDataInternal(dispatchable, &data);
+}
+
+inline InstanceData& GetData(VkInstance instance) {
+    return *reinterpret_cast<InstanceData*>(GetDataInternal(instance));
+}
+
+inline InstanceData& GetData(VkPhysicalDevice physical_dev) {
+    return *reinterpret_cast<InstanceData*>(GetDataInternal(physical_dev));
+}
+
+inline InstanceData& GetData(InstanceDispatchable dispatchable) {
+    return *reinterpret_cast<InstanceData*>(GetDataInternal(dispatchable));
+}
+
+inline DeviceData& GetData(VkDevice dev) {
+    return *reinterpret_cast<DeviceData*>(GetDataInternal(dev));
+}
+
+inline DeviceData& GetData(VkQueue queue) {
+    return *reinterpret_cast<DeviceData*>(GetDataInternal(queue));
+}
+
+inline DeviceData& GetData(VkCommandBuffer cmd) {
+    return *reinterpret_cast<DeviceData*>(GetDataInternal(cmd));
+}
+
+inline DeviceData& GetData(DeviceDispatchable dispatchable) {
+    return *reinterpret_cast<DeviceData*>(GetDataInternal(dispatchable));
+}
+
+}  // namespace driver
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_DRIVER_H
diff --git a/vulkan/libvulkan/driver_gen.cpp b/vulkan/libvulkan/driver_gen.cpp
new file mode 100644
index 0000000..5bd2159
--- /dev/null
+++ b/vulkan/libvulkan/driver_gen.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#include <string.h>
+#include <algorithm>
+#include <log/log.h>
+
+#include "driver.h"
+
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+// clang-format off
+
+VKAPI_ATTR VkResult checkedCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        return CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
+    } else {
+        ALOGE("VK_KHR_swapchain not enabled. vkCreateSwapchainKHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR void checkedDestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        DestroySwapchainKHR(device, swapchain, pAllocator);
+    } else {
+        ALOGE("VK_KHR_swapchain not enabled. vkDestroySwapchainKHR not executed.");
+    }
+}
+
+VKAPI_ATTR VkResult checkedGetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t* pSwapchainImageCount, VkImage* pSwapchainImages) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        return GetSwapchainImagesKHR(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+    } else {
+        ALOGE("VK_KHR_swapchain not enabled. vkGetSwapchainImagesKHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR VkResult checkedAcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* pImageIndex) {
+    if (GetData(device).hook_extensions[ProcHook::KHR_swapchain]) {
+        return AcquireNextImageKHR(device, swapchain, timeout, semaphore, fence, pImageIndex);
+    } else {
+        ALOGE("VK_KHR_swapchain not enabled. vkAcquireNextImageKHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+VKAPI_ATTR VkResult checkedQueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* pPresentInfo) {
+    if (GetData(queue).hook_extensions[ProcHook::KHR_swapchain]) {
+        return QueuePresentKHR(queue, pPresentInfo);
+    } else {
+        ALOGE("VK_KHR_swapchain not enabled. vkQueuePresentKHR not executed.");
+        return VK_SUCCESS;
+    }
+}
+
+// clang-format on
+
+const ProcHook g_proc_hooks[] = {
+    // clang-format off
+    {
+        "vkAcquireImageANDROID",
+        ProcHook::DEVICE,
+        ProcHook::ANDROID_native_buffer,
+        nullptr,
+        nullptr,
+    },
+    {
+        "vkAcquireNextImageKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(AcquireNextImageKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedAcquireNextImageKHR),
+    },
+    {
+        "vkAllocateCommandBuffers",
+        ProcHook::DEVICE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers),
+        nullptr,
+    },
+    {
+        "vkCreateAndroidSurfaceKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_android_surface,
+        reinterpret_cast<PFN_vkVoidFunction>(CreateAndroidSurfaceKHR),
+        nullptr,
+    },
+    {
+        "vkCreateDebugReportCallbackEXT",
+        ProcHook::INSTANCE,
+        ProcHook::EXT_debug_report,
+        reinterpret_cast<PFN_vkVoidFunction>(CreateDebugReportCallbackEXT),
+        nullptr,
+    },
+    {
+        "vkCreateDevice",
+        ProcHook::INSTANCE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(CreateDevice),
+        nullptr,
+    },
+    {
+        "vkCreateInstance",
+        ProcHook::GLOBAL,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(CreateInstance),
+        nullptr,
+    },
+    {
+        "vkCreateSwapchainKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(CreateSwapchainKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedCreateSwapchainKHR),
+    },
+    {
+        "vkDebugReportMessageEXT",
+        ProcHook::INSTANCE,
+        ProcHook::EXT_debug_report,
+        reinterpret_cast<PFN_vkVoidFunction>(DebugReportMessageEXT),
+        nullptr,
+    },
+    {
+        "vkDestroyDebugReportCallbackEXT",
+        ProcHook::INSTANCE,
+        ProcHook::EXT_debug_report,
+        reinterpret_cast<PFN_vkVoidFunction>(DestroyDebugReportCallbackEXT),
+        nullptr,
+    },
+    {
+        "vkDestroyDevice",
+        ProcHook::DEVICE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice),
+        nullptr,
+    },
+    {
+        "vkDestroyInstance",
+        ProcHook::INSTANCE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance),
+        nullptr,
+    },
+    {
+        "vkDestroySurfaceKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_surface,
+        reinterpret_cast<PFN_vkVoidFunction>(DestroySurfaceKHR),
+        nullptr,
+    },
+    {
+        "vkDestroySwapchainKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(DestroySwapchainKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedDestroySwapchainKHR),
+    },
+    {
+        "vkEnumerateDeviceExtensionProperties",
+        ProcHook::INSTANCE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties),
+        nullptr,
+    },
+    {
+        "vkEnumerateInstanceExtensionProperties",
+        ProcHook::GLOBAL,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties),
+        nullptr,
+    },
+    {
+        "vkEnumeratePhysicalDevices",
+        ProcHook::INSTANCE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices),
+        nullptr,
+    },
+    {
+        "vkGetDeviceProcAddr",
+        ProcHook::DEVICE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr),
+        nullptr,
+    },
+    {
+        "vkGetDeviceQueue",
+        ProcHook::DEVICE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue),
+        nullptr,
+    },
+    {
+        "vkGetInstanceProcAddr",
+        ProcHook::INSTANCE,
+        ProcHook::EXTENSION_CORE,
+        reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr),
+        nullptr,
+    },
+    {
+        "vkGetPhysicalDeviceSurfaceCapabilitiesKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_surface,
+        reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceCapabilitiesKHR),
+        nullptr,
+    },
+    {
+        "vkGetPhysicalDeviceSurfaceFormatsKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_surface,
+        reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceFormatsKHR),
+        nullptr,
+    },
+    {
+        "vkGetPhysicalDeviceSurfacePresentModesKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_surface,
+        reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfacePresentModesKHR),
+        nullptr,
+    },
+    {
+        "vkGetPhysicalDeviceSurfaceSupportKHR",
+        ProcHook::INSTANCE,
+        ProcHook::KHR_surface,
+        reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSurfaceSupportKHR),
+        nullptr,
+    },
+    {
+        "vkGetSwapchainGrallocUsageANDROID",
+        ProcHook::DEVICE,
+        ProcHook::ANDROID_native_buffer,
+        nullptr,
+        nullptr,
+    },
+    {
+        "vkGetSwapchainImagesKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(GetSwapchainImagesKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedGetSwapchainImagesKHR),
+    },
+    {
+        "vkQueuePresentKHR",
+        ProcHook::DEVICE,
+        ProcHook::KHR_swapchain,
+        reinterpret_cast<PFN_vkVoidFunction>(QueuePresentKHR),
+        reinterpret_cast<PFN_vkVoidFunction>(checkedQueuePresentKHR),
+    },
+    {
+        "vkQueueSignalReleaseImageANDROID",
+        ProcHook::DEVICE,
+        ProcHook::ANDROID_native_buffer,
+        nullptr,
+        nullptr,
+    },
+    // clang-format on
+};
+
+}  // anonymous
+
+const ProcHook* GetProcHook(const char* name) {
+    const auto& begin = g_proc_hooks;
+    const auto& end =
+        g_proc_hooks + sizeof(g_proc_hooks) / sizeof(g_proc_hooks[0]);
+    const auto hook = std::lower_bound(
+        begin, end, name,
+        [](const ProcHook& e, const char* n) { return strcmp(e.name, n) < 0; });
+    return (hook < end && strcmp(hook->name, name) == 0) ? hook : nullptr;
+}
+
+ProcHook::Extension GetProcHookExtension(const char* name) {
+    // clang-format off
+    if (strcmp(name, "VK_ANDROID_native_buffer") == 0) return ProcHook::ANDROID_native_buffer;
+    if (strcmp(name, "VK_EXT_debug_report") == 0) return ProcHook::EXT_debug_report;
+    if (strcmp(name, "VK_KHR_android_surface") == 0) return ProcHook::KHR_android_surface;
+    if (strcmp(name, "VK_KHR_surface") == 0) return ProcHook::KHR_surface;
+    if (strcmp(name, "VK_KHR_swapchain") == 0) return ProcHook::KHR_swapchain;
+    // clang-format on
+    return ProcHook::EXTENSION_UNKNOWN;
+}
+
+#define UNLIKELY(expr) __builtin_expect((expr), 0)
+
+#define INIT_PROC(obj, proc)                                           \
+    do {                                                               \
+        data.driver.proc =                                             \
+            reinterpret_cast<PFN_vk##proc>(get_proc(obj, "vk" #proc)); \
+        if (UNLIKELY(!data.driver.proc)) {                             \
+            ALOGE("missing " #obj " proc: vk" #proc);                  \
+            success = false;                                           \
+        }                                                              \
+    } while (0)
+
+#define INIT_PROC_EXT(ext, obj, proc)  \
+    do {                               \
+        if (extensions[ProcHook::ext]) \
+            INIT_PROC(obj, proc);      \
+    } while (0)
+
+bool InitDriverTable(VkInstance instance,
+                     PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(instance);
+    bool success = true;
+
+    // clang-format off
+    INIT_PROC(instance, DestroyInstance);
+    INIT_PROC(instance, EnumeratePhysicalDevices);
+    INIT_PROC(instance, GetInstanceProcAddr);
+    INIT_PROC(instance, CreateDevice);
+    INIT_PROC(instance, EnumerateDeviceLayerProperties);
+    INIT_PROC(instance, EnumerateDeviceExtensionProperties);
+    INIT_PROC_EXT(EXT_debug_report, instance, CreateDebugReportCallbackEXT);
+    INIT_PROC_EXT(EXT_debug_report, instance, DestroyDebugReportCallbackEXT);
+    INIT_PROC_EXT(EXT_debug_report, instance, DebugReportMessageEXT);
+    // clang-format on
+
+    return success;
+}
+
+bool InitDriverTable(VkDevice dev,
+                     PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions) {
+    auto& data = GetData(dev);
+    bool success = true;
+
+    // clang-format off
+    INIT_PROC(dev, GetDeviceProcAddr);
+    INIT_PROC(dev, DestroyDevice);
+    INIT_PROC(dev, GetDeviceQueue);
+    INIT_PROC(dev, CreateImage);
+    INIT_PROC(dev, DestroyImage);
+    INIT_PROC(dev, AllocateCommandBuffers);
+    INIT_PROC_EXT(ANDROID_native_buffer, dev, GetSwapchainGrallocUsageANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, dev, AcquireImageANDROID);
+    INIT_PROC_EXT(ANDROID_native_buffer, dev, QueueSignalReleaseImageANDROID);
+    // clang-format on
+
+    return success;
+}
+
+}  // namespace driver
+}  // namespace vulkan
+
+// clang-format on
diff --git a/vulkan/libvulkan/driver_gen.h b/vulkan/libvulkan/driver_gen.h
new file mode 100644
index 0000000..ca17d57
--- /dev/null
+++ b/vulkan/libvulkan/driver_gen.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#ifndef LIBVULKAN_DRIVER_GEN_H
+#define LIBVULKAN_DRIVER_GEN_H
+
+#include <bitset>
+#include <vulkan/vulkan.h>
+#include <vulkan/vk_android_native_buffer.h>
+
+namespace vulkan {
+namespace driver {
+
+struct ProcHook {
+    enum Type {
+        GLOBAL,
+        INSTANCE,
+        DEVICE,
+    };
+    enum Extension {
+        ANDROID_native_buffer,
+        EXT_debug_report,
+        KHR_android_surface,
+        KHR_surface,
+        KHR_swapchain,
+
+        EXTENSION_CORE,  // valid bit
+        EXTENSION_COUNT,
+        EXTENSION_UNKNOWN,
+    };
+
+    const char* name;
+    Type type;
+    Extension extension;
+
+    PFN_vkVoidFunction proc;
+    PFN_vkVoidFunction checked_proc;  // always nullptr for non-device hooks
+};
+
+struct InstanceDriverTable {
+    // clang-format off
+    PFN_vkDestroyInstance DestroyInstance;
+    PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
+    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+    PFN_vkCreateDevice CreateDevice;
+    PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
+    PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties;
+    PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
+    PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
+    PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
+    // clang-format on
+};
+
+struct DeviceDriverTable {
+    // clang-format off
+    PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
+    PFN_vkDestroyDevice DestroyDevice;
+    PFN_vkGetDeviceQueue GetDeviceQueue;
+    PFN_vkCreateImage CreateImage;
+    PFN_vkDestroyImage DestroyImage;
+    PFN_vkAllocateCommandBuffers AllocateCommandBuffers;
+    PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
+    PFN_vkAcquireImageANDROID AcquireImageANDROID;
+    PFN_vkQueueSignalReleaseImageANDROID QueueSignalReleaseImageANDROID;
+    // clang-format on
+};
+
+const ProcHook* GetProcHook(const char* name);
+ProcHook::Extension GetProcHookExtension(const char* name);
+
+bool InitDriverTable(VkInstance instance,
+                     PFN_vkGetInstanceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+bool InitDriverTable(VkDevice dev,
+                     PFN_vkGetDeviceProcAddr get_proc,
+                     const std::bitset<ProcHook::EXTENSION_COUNT>& extensions);
+
+}  // namespace driver
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_DRIVER_TABLE_H
diff --git a/vulkan/libvulkan/layers_extensions.cpp b/vulkan/libvulkan/layers_extensions.cpp
new file mode 100644
index 0000000..f9b1002
--- /dev/null
+++ b/vulkan/libvulkan/layers_extensions.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// #define LOG_NDEBUG 0
+
+#include "layers_extensions.h"
+#include <alloca.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <mutex>
+#include <sys/prctl.h>
+#include <string>
+#include <string.h>
+#include <vector>
+#include <log/log.h>
+#include <vulkan/vulkan_loader_data.h>
+
+// TODO(jessehall): The whole way we deal with extensions is pretty hokey, and
+// not a good long-term solution. Having a hard-coded enum of extensions is
+// bad, of course. Representing sets of extensions (requested, supported, etc.)
+// as a bitset isn't necessarily bad, if the mapping from extension to bit were
+// dynamic. Need to rethink this completely when there's a little more time.
+
+// TODO(jessehall): This file currently builds up global data structures as it
+// loads, and never cleans them up. This means we're doing heap allocations
+// without going through an app-provided allocator, but worse, we'll leak those
+// allocations if the loader is unloaded.
+//
+// We should allocate "enough" BSS space, and suballocate from there. Will
+// probably want to intern strings, etc., and will need some custom/manual data
+// structures.
+
+namespace vulkan {
+namespace api {
+
+struct Layer {
+    VkLayerProperties properties;
+    size_t library_idx;
+
+    // true if the layer intercepts vkCreateDevice and device commands
+    bool is_global;
+
+    std::vector<VkExtensionProperties> instance_extensions;
+    std::vector<VkExtensionProperties> device_extensions;
+};
+
+namespace {
+
+class LayerLibrary {
+   public:
+    LayerLibrary(const std::string& path)
+        : path_(path), dlhandle_(nullptr), refcount_(0) {}
+
+    LayerLibrary(LayerLibrary&& other)
+        : path_(std::move(other.path_)),
+          dlhandle_(other.dlhandle_),
+          refcount_(other.refcount_) {
+        other.dlhandle_ = nullptr;
+        other.refcount_ = 0;
+    }
+
+    LayerLibrary(const LayerLibrary&) = delete;
+    LayerLibrary& operator=(const LayerLibrary&) = delete;
+
+    // these are thread-safe
+    bool Open();
+    void Close();
+
+    bool EnumerateLayers(size_t library_idx,
+                         std::vector<Layer>& instance_layers) const;
+
+    void* GetGPA(const Layer& layer,
+                 const char* gpa_name,
+                 size_t gpa_name_len) const;
+
+   private:
+    const std::string path_;
+
+    std::mutex mutex_;
+    void* dlhandle_;
+    size_t refcount_;
+};
+
+bool LayerLibrary::Open() {
+    std::lock_guard<std::mutex> lock(mutex_);
+
+    if (refcount_++ == 0) {
+        dlhandle_ = dlopen(path_.c_str(), RTLD_NOW | RTLD_LOCAL);
+        ALOGV("Opening library %s", path_.c_str());
+        if (!dlhandle_) {
+            ALOGE("failed to load layer library '%s': %s", path_.c_str(),
+                  dlerror());
+            refcount_ = 0;
+            return false;
+        }
+    }
+    ALOGV("Refcount on activate is %zu", refcount_);
+    return true;
+}
+
+void LayerLibrary::Close() {
+    std::lock_guard<std::mutex> lock(mutex_);
+
+    if (--refcount_ == 0) {
+        ALOGV("Closing library %s", path_.c_str());
+        dlclose(dlhandle_);
+        dlhandle_ = nullptr;
+    }
+    ALOGV("Refcount on destruction is %zu", refcount_);
+}
+
+bool LayerLibrary::EnumerateLayers(size_t library_idx,
+                                   std::vector<Layer>& instance_layers) const {
+    PFN_vkEnumerateInstanceLayerProperties enumerate_instance_layers =
+        reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
+            dlsym(dlhandle_, "vkEnumerateInstanceLayerProperties"));
+    PFN_vkEnumerateInstanceExtensionProperties enumerate_instance_extensions =
+        reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
+            dlsym(dlhandle_, "vkEnumerateInstanceExtensionProperties"));
+    if (!enumerate_instance_layers || !enumerate_instance_extensions) {
+        ALOGV("layer library '%s' misses some instance enumeraion functions",
+              path_.c_str());
+        return false;
+    }
+
+    // device functions are optional
+    PFN_vkEnumerateDeviceLayerProperties enumerate_device_layers =
+        reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
+            dlsym(dlhandle_, "vkEnumerateDeviceLayerProperties"));
+    PFN_vkEnumerateDeviceExtensionProperties enumerate_device_extensions =
+        reinterpret_cast<PFN_vkEnumerateDeviceExtensionProperties>(
+            dlsym(dlhandle_, "vkEnumerateDeviceExtensionProperties"));
+
+    // get layer counts
+    uint32_t num_instance_layers = 0;
+    uint32_t num_device_layers = 0;
+    VkResult result = enumerate_instance_layers(&num_instance_layers, nullptr);
+    if (result != VK_SUCCESS || !num_instance_layers) {
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateInstanceLayerProperties failed for library '%s': "
+                "%d",
+                path_.c_str(), result);
+        }
+        return false;
+    }
+    if (enumerate_device_layers) {
+        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
+                                         nullptr);
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
+                path_.c_str(), result);
+            return false;
+        }
+    }
+
+    // get layer properties
+    VkLayerProperties* properties = static_cast<VkLayerProperties*>(alloca(
+        (num_instance_layers + num_device_layers) * sizeof(VkLayerProperties)));
+    result = enumerate_instance_layers(&num_instance_layers, properties);
+    if (result != VK_SUCCESS) {
+        ALOGW("vkEnumerateInstanceLayerProperties failed for library '%s': %d",
+              path_.c_str(), result);
+        return false;
+    }
+    if (num_device_layers > 0) {
+        result = enumerate_device_layers(VK_NULL_HANDLE, &num_device_layers,
+                                         properties + num_instance_layers);
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateDeviceLayerProperties failed for library '%s': %d",
+                path_.c_str(), result);
+            return false;
+        }
+    }
+
+    // append layers to instance_layers
+    size_t prev_num_instance_layers = instance_layers.size();
+    instance_layers.reserve(prev_num_instance_layers + num_instance_layers);
+    for (size_t i = 0; i < num_instance_layers; i++) {
+        const VkLayerProperties& props = properties[i];
+
+        Layer layer;
+        layer.properties = props;
+        layer.library_idx = library_idx;
+        layer.is_global = false;
+
+        uint32_t count = 0;
+        result =
+            enumerate_instance_extensions(props.layerName, &count, nullptr);
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+                "'%s': %d",
+                props.layerName, path_.c_str(), result);
+            instance_layers.resize(prev_num_instance_layers);
+            return false;
+        }
+        layer.instance_extensions.resize(count);
+        result = enumerate_instance_extensions(
+            props.layerName, &count, layer.instance_extensions.data());
+        if (result != VK_SUCCESS) {
+            ALOGW(
+                "vkEnumerateInstanceExtensionProperties(%s) failed for library "
+                "'%s': %d",
+                props.layerName, path_.c_str(), result);
+            instance_layers.resize(prev_num_instance_layers);
+            return false;
+        }
+
+        for (size_t j = 0; j < num_device_layers; j++) {
+            const auto& dev_props = properties[num_instance_layers + j];
+            if (memcmp(&props, &dev_props, sizeof(props)) == 0) {
+                layer.is_global = true;
+                break;
+            }
+        }
+
+        if (layer.is_global && enumerate_device_extensions) {
+            result = enumerate_device_extensions(
+                VK_NULL_HANDLE, props.layerName, &count, nullptr);
+            if (result != VK_SUCCESS) {
+                ALOGW(
+                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
+                    "library '%s': %d",
+                    props.layerName, path_.c_str(), result);
+                instance_layers.resize(prev_num_instance_layers);
+                return false;
+            }
+            layer.device_extensions.resize(count);
+            result = enumerate_device_extensions(
+                VK_NULL_HANDLE, props.layerName, &count,
+                layer.device_extensions.data());
+            if (result != VK_SUCCESS) {
+                ALOGW(
+                    "vkEnumerateDeviceExtensionProperties(%s) failed for "
+                    "library '%s': %d",
+                    props.layerName, path_.c_str(), result);
+                instance_layers.resize(prev_num_instance_layers);
+                return false;
+            }
+        }
+
+        instance_layers.push_back(layer);
+        ALOGV("  added %s layer '%s'",
+              (layer.is_global) ? "global" : "instance", props.layerName);
+    }
+
+    return true;
+}
+
+void* LayerLibrary::GetGPA(const Layer& layer,
+                           const char* gpa_name,
+                           size_t gpa_name_len) const {
+    void* gpa;
+    size_t layer_name_len =
+        std::max(size_t{2}, strlen(layer.properties.layerName));
+    char* name = static_cast<char*>(alloca(layer_name_len + gpa_name_len + 1));
+    strcpy(name, layer.properties.layerName);
+    strcpy(name + layer_name_len, gpa_name);
+    if (!(gpa = dlsym(dlhandle_, name))) {
+        strcpy(name, "vk");
+        strcpy(name + 2, gpa_name);
+        gpa = dlsym(dlhandle_, name);
+    }
+    return gpa;
+}
+
+std::vector<LayerLibrary> g_layer_libraries;
+std::vector<Layer> g_instance_layers;
+
+void AddLayerLibrary(const std::string& path) {
+    ALOGV("examining layer library '%s'", path.c_str());
+
+    LayerLibrary library(path);
+    if (!library.Open())
+        return;
+
+    if (!library.EnumerateLayers(g_layer_libraries.size(), g_instance_layers)) {
+        library.Close();
+        return;
+    }
+
+    library.Close();
+
+    g_layer_libraries.emplace_back(std::move(library));
+}
+
+void DiscoverLayersInDirectory(const std::string& dir_path) {
+    ALOGV("looking for layers in '%s'", dir_path.c_str());
+
+    DIR* directory = opendir(dir_path.c_str());
+    if (!directory) {
+        int err = errno;
+        ALOGV_IF(err != ENOENT, "failed to open layer directory '%s': %s (%d)",
+                 dir_path.c_str(), strerror(err), err);
+        return;
+    }
+
+    std::string path;
+    path.reserve(dir_path.size() + 20);
+    path.append(dir_path);
+    path.append("/");
+
+    struct dirent* entry;
+    while ((entry = readdir(directory))) {
+        size_t libname_len = strlen(entry->d_name);
+        if (strncmp(entry->d_name, "libVkLayer", 10) != 0 ||
+            strncmp(entry->d_name + libname_len - 3, ".so", 3) != 0)
+            continue;
+        path.append(entry->d_name);
+        AddLayerLibrary(path);
+        path.resize(dir_path.size() + 1);
+    }
+
+    closedir(directory);
+}
+
+const VkExtensionProperties* FindExtension(
+    const std::vector<VkExtensionProperties>& extensions,
+    const char* name) {
+    auto it = std::find_if(extensions.cbegin(), extensions.cend(),
+                           [=](const VkExtensionProperties& ext) {
+                               return (strcmp(ext.extensionName, name) == 0);
+                           });
+    return (it != extensions.cend()) ? &*it : nullptr;
+}
+
+void* GetLayerGetProcAddr(const Layer& layer,
+                          const char* gpa_name,
+                          size_t gpa_name_len) {
+    const LayerLibrary& library = g_layer_libraries[layer.library_idx];
+    return library.GetGPA(layer, gpa_name, gpa_name_len);
+}
+
+}  // anonymous namespace
+
+void DiscoverLayers() {
+    if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0))
+        DiscoverLayersInDirectory("/data/local/debug/vulkan");
+    if (!LoaderData::GetInstance().layer_path.empty())
+        DiscoverLayersInDirectory(LoaderData::GetInstance().layer_path.c_str());
+}
+
+uint32_t GetLayerCount() {
+    return static_cast<uint32_t>(g_instance_layers.size());
+}
+
+const Layer& GetLayer(uint32_t index) {
+    return g_instance_layers[index];
+}
+
+const Layer* FindLayer(const char* name) {
+    auto layer =
+        std::find_if(g_instance_layers.cbegin(), g_instance_layers.cend(),
+                     [=](const Layer& entry) {
+                         return strcmp(entry.properties.layerName, name) == 0;
+                     });
+    return (layer != g_instance_layers.cend()) ? &*layer : nullptr;
+}
+
+const VkLayerProperties& GetLayerProperties(const Layer& layer) {
+    return layer.properties;
+}
+
+bool IsLayerGlobal(const Layer& layer) {
+    return layer.is_global;
+}
+
+const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
+                                                        uint32_t& count) {
+    count = static_cast<uint32_t>(layer.instance_extensions.size());
+    return layer.instance_extensions.data();
+}
+
+const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
+                                                      uint32_t& count) {
+    count = static_cast<uint32_t>(layer.device_extensions.size());
+    return layer.device_extensions.data();
+}
+
+const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
+                                                        const char* name) {
+    return FindExtension(layer.instance_extensions, name);
+}
+
+const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
+                                                      const char* name) {
+    return FindExtension(layer.device_extensions, name);
+}
+
+LayerRef GetLayerRef(const Layer& layer) {
+    LayerLibrary& library = g_layer_libraries[layer.library_idx];
+    return LayerRef((library.Open()) ? &layer : nullptr);
+}
+
+LayerRef::LayerRef(const Layer* layer) : layer_(layer) {}
+
+LayerRef::~LayerRef() {
+    if (layer_) {
+        LayerLibrary& library = g_layer_libraries[layer_->library_idx];
+        library.Close();
+    }
+}
+
+LayerRef::LayerRef(LayerRef&& other) : layer_(other.layer_) {
+    other.layer_ = nullptr;
+}
+
+PFN_vkGetInstanceProcAddr LayerRef::GetGetInstanceProcAddr() const {
+    return layer_ ? reinterpret_cast<PFN_vkGetInstanceProcAddr>(
+                        GetLayerGetProcAddr(*layer_, "GetInstanceProcAddr", 19))
+                  : nullptr;
+}
+
+PFN_vkGetDeviceProcAddr LayerRef::GetGetDeviceProcAddr() const {
+    return layer_ ? reinterpret_cast<PFN_vkGetDeviceProcAddr>(
+                        GetLayerGetProcAddr(*layer_, "GetDeviceProcAddr", 17))
+                  : nullptr;
+}
+
+}  // namespace api
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/layers_extensions.h b/vulkan/libvulkan/layers_extensions.h
new file mode 100644
index 0000000..79fe59d
--- /dev/null
+++ b/vulkan/libvulkan/layers_extensions.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LIBVULKAN_LAYERS_EXTENSIONS_H
+#define LIBVULKAN_LAYERS_EXTENSIONS_H 1
+
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+namespace api {
+
+struct Layer;
+
+class LayerRef {
+   public:
+    LayerRef(const Layer* layer);
+    LayerRef(LayerRef&& other);
+    ~LayerRef();
+    LayerRef(const LayerRef&) = delete;
+    LayerRef& operator=(const LayerRef&) = delete;
+
+    // provides bool-like behavior
+    operator const Layer*() const { return layer_; }
+
+    PFN_vkGetInstanceProcAddr GetGetInstanceProcAddr() const;
+    PFN_vkGetDeviceProcAddr GetGetDeviceProcAddr() const;
+
+   private:
+    const Layer* layer_;
+};
+
+void DiscoverLayers();
+
+uint32_t GetLayerCount();
+const Layer& GetLayer(uint32_t index);
+const Layer* FindLayer(const char* name);
+
+const VkLayerProperties& GetLayerProperties(const Layer& layer);
+bool IsLayerGlobal(const Layer& layer);
+const VkExtensionProperties* GetLayerInstanceExtensions(const Layer& layer,
+                                                        uint32_t& count);
+const VkExtensionProperties* GetLayerDeviceExtensions(const Layer& layer,
+                                                      uint32_t& count);
+
+const VkExtensionProperties* FindLayerInstanceExtension(const Layer& layer,
+                                                        const char* name);
+const VkExtensionProperties* FindLayerDeviceExtension(const Layer& layer,
+                                                      const char* name);
+
+LayerRef GetLayerRef(const Layer& layer);
+
+}  // namespace api
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_LAYERS_EXTENSIONS_H
diff --git a/vulkan/libvulkan/stubhal.cpp b/vulkan/libvulkan/stubhal.cpp
new file mode 100644
index 0000000..a74d370
--- /dev/null
+++ b/vulkan/libvulkan/stubhal.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+/* NOTE:
+ * This stub HAL is only used internally by the loader when a real HAL
+ * implementation is not present, in order to avoid needing "null HAL" checks
+ * throughout the loader. It does not enumerate any physical devices, and is
+ * only as conformant to the Vulkan and Android HAL interfaces as the loader
+ * needs it to be. Do not use it as an example of a correct implementation; the
+ * code in ../null_driver is better for that.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "vkstub"
+
+#include <array>
+#include <bitset>
+#include <mutex>
+#include <hardware/hwvulkan.h>
+#include <log/log.h>
+#include "stubhal.h"
+
+namespace vulkan {
+namespace stubhal {
+
+namespace {
+
+const size_t kMaxInstances = 32;
+static std::mutex g_instance_mutex;
+static std::bitset<kMaxInstances> g_instance_used(false);
+static std::array<hwvulkan_dispatch_t, kMaxInstances> g_instances;
+
+[[noreturn]] void NoOp() {
+    LOG_ALWAYS_FATAL("invalid stub function called");
+}
+
+VKAPI_ATTR VkResult
+EnumerateInstanceExtensionProperties(const char* /*layer_name*/,
+                                     uint32_t* count,
+                                     VkExtensionProperties* /*properties*/) {
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult
+EnumerateInstanceLayerProperties(uint32_t* count,
+                                 VkLayerProperties* /*properties*/) {
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* /*create_info*/,
+                                   const VkAllocationCallbacks* /*allocator*/,
+                                   VkInstance* instance) {
+    std::lock_guard<std::mutex> lock(g_instance_mutex);
+    for (size_t i = 0; i < kMaxInstances; i++) {
+        if (!g_instance_used[i]) {
+            g_instance_used[i] = true;
+            g_instances[i].magic = HWVULKAN_DISPATCH_MAGIC;
+            *instance = reinterpret_cast<VkInstance>(&g_instances[i]);
+            return VK_SUCCESS;
+        }
+    }
+    ALOGE("no more instances available (max=%zu)", kMaxInstances);
+    return VK_ERROR_INITIALIZATION_FAILED;
+}
+
+VKAPI_ATTR void DestroyInstance(VkInstance instance,
+                                const VkAllocationCallbacks* /*allocator*/) {
+    std::lock_guard<std::mutex> lock(g_instance_mutex);
+    ssize_t idx =
+        reinterpret_cast<hwvulkan_dispatch_t*>(instance) - &g_instances[0];
+    ALOG_ASSERT(idx >= 0 && static_cast<size_t>(idx) < g_instance_used.size(),
+                "DestroyInstance: invalid instance handle");
+    g_instance_used[static_cast<size_t>(idx)] = false;
+}
+
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance /*instance*/,
+                                             uint32_t* count,
+                                             VkPhysicalDevice* /*gpus*/) {
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance /*instance*/,
+                                                  const char* name) {
+    if (strcmp(name, "vkCreateInstance") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(CreateInstance);
+    if (strcmp(name, "vkDestroyInstance") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance);
+    if (strcmp(name, "vkEnumerateInstanceExtensionProperties") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            EnumerateInstanceExtensionProperties);
+    if (strcmp(name, "vkEnumeratePhysicalDevices") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices);
+    if (strcmp(name, "vkGetInstanceProcAddr") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr);
+
+    // None of the other Vulkan functions should ever be called, as they all
+    // take a VkPhysicalDevice or other object obtained from a physical device.
+    return reinterpret_cast<PFN_vkVoidFunction>(NoOp);
+}
+
+}  // anonymous namespace
+
+const hwvulkan_device_t kDevice = {
+    .common =
+        {
+            .tag = HARDWARE_DEVICE_TAG,
+            .version = HWVULKAN_DEVICE_API_VERSION_0_1,
+            .module = nullptr,
+            .close = nullptr,
+        },
+    .EnumerateInstanceExtensionProperties =
+        EnumerateInstanceExtensionProperties,
+    .CreateInstance = CreateInstance,
+    .GetInstanceProcAddr = GetInstanceProcAddr,
+};
+
+}  // namespace stubhal
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/stubhal.h b/vulkan/libvulkan/stubhal.h
new file mode 100644
index 0000000..9ba7d04
--- /dev/null
+++ b/vulkan/libvulkan/stubhal.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LIBVULKAN_STUBHAL_H
+#define LIBVULKAN_STUBHAL_H 1
+
+struct hwvulkan_device_t;
+
+namespace vulkan {
+namespace stubhal {
+
+extern const hwvulkan_device_t kDevice;
+
+}  // namespace stubhal
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_STUBHAL_H
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
new file mode 100644
index 0000000..69e8e84
--- /dev/null
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -0,0 +1,803 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 <algorithm>
+
+#include <gui/BufferQueue.h>
+#include <log/log.h>
+#include <sync/sync.h>
+#include <utils/StrongPointer.h>
+
+#include "driver.h"
+
+// TODO(jessehall): Currently we don't have a good error code for when a native
+// window operation fails. Just returning INITIALIZATION_FAILED for now. Later
+// versions (post SDK 0.9) of the API/extension have a better error code.
+// When updating to that version, audit all error returns.
+namespace vulkan {
+namespace driver {
+
+namespace {
+
+const VkSurfaceTransformFlagsKHR kSupportedTransforms =
+    VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR |
+    VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR |
+    VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR |
+    VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR |
+    // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
+    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR |
+    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR |
+    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR |
+    // VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
+    VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
+
+VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
+    // Native and Vulkan transforms are isomorphic, but are represented
+    // differently. Vulkan transforms are built up of an optional horizontal
+    // mirror, followed by a clockwise 0/90/180/270-degree rotation. Native
+    // transforms are built up from a horizontal flip, vertical flip, and
+    // 90-degree rotation, all optional but always in that order.
+
+    // TODO(jessehall): For now, only support pure rotations, not
+    // flip or flip-and-rotate, until I have more time to test them and build
+    // sample code. As far as I know we never actually use anything besides
+    // pure rotations anyway.
+
+    switch (native) {
+        case 0:  // 0x0
+            return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+        // case NATIVE_WINDOW_TRANSFORM_FLIP_H:  // 0x1
+        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR;
+        // case NATIVE_WINDOW_TRANSFORM_FLIP_V:  // 0x2
+        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_180:  // FLIP_H | FLIP_V
+            return VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_90:  // 0x4
+            return VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR;
+        // case NATIVE_WINDOW_TRANSFORM_FLIP_H | NATIVE_WINDOW_TRANSFORM_ROT_90:
+        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR;
+        // case NATIVE_WINDOW_TRANSFORM_FLIP_V | NATIVE_WINDOW_TRANSFORM_ROT_90:
+        //     return VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_ROT_270:  // FLIP_H | FLIP_V | ROT_90
+            return VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR;
+        case NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY:
+        default:
+            return VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+    }
+}
+
+int InvertTransformToNative(VkSurfaceTransformFlagBitsKHR transform) {
+    switch (transform) {
+        case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_270;
+        case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_180;
+        case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+            return NATIVE_WINDOW_TRANSFORM_ROT_90;
+        // TODO(jessehall): See TODO in TranslateNativeToVulkanTransform.
+        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR:
+        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H;
+        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR:
+        //     return NATIVE_WINDOW_TRANSFORM_FLIP_H |
+        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
+        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR:
+        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V;
+        // case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR:
+        //     return NATIVE_WINDOW_TRANSFORM_FLIP_V |
+        //            NATIVE_WINDOW_TRANSFORM_ROT_90;
+        case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+        case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+        default:
+            return 0;
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+struct Surface {
+    android::sp<ANativeWindow> window;
+};
+
+VkSurfaceKHR HandleFromSurface(Surface* surface) {
+    return VkSurfaceKHR(reinterpret_cast<uint64_t>(surface));
+}
+
+Surface* SurfaceFromHandle(VkSurfaceKHR handle) {
+    return reinterpret_cast<Surface*>(handle);
+}
+
+struct Swapchain {
+    Swapchain(Surface& surface_, uint32_t num_images_)
+        : surface(surface_), num_images(num_images_) {}
+
+    Surface& surface;
+    uint32_t num_images;
+
+    struct Image {
+        Image() : image(VK_NULL_HANDLE), dequeue_fence(-1), dequeued(false) {}
+        VkImage image;
+        android::sp<ANativeWindowBuffer> buffer;
+        // The fence is only valid when the buffer is dequeued, and should be
+        // -1 any other time. When valid, we own the fd, and must ensure it is
+        // closed: either by closing it explicitly when queueing the buffer,
+        // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
+        int dequeue_fence;
+        bool dequeued;
+    } images[android::BufferQueue::NUM_BUFFER_SLOTS];
+};
+
+VkSwapchainKHR HandleFromSwapchain(Swapchain* swapchain) {
+    return VkSwapchainKHR(reinterpret_cast<uint64_t>(swapchain));
+}
+
+Swapchain* SwapchainFromHandle(VkSwapchainKHR handle) {
+    return reinterpret_cast<Swapchain*>(handle);
+}
+
+}  // anonymous namespace
+
+VKAPI_ATTR
+VkResult CreateAndroidSurfaceKHR(
+    VkInstance instance,
+    const VkAndroidSurfaceCreateInfoKHR* pCreateInfo,
+    const VkAllocationCallbacks* allocator,
+    VkSurfaceKHR* out_surface) {
+    if (!allocator)
+        allocator = &GetData(instance).allocator;
+    void* mem = allocator->pfnAllocation(allocator->pUserData, sizeof(Surface),
+                                         alignof(Surface),
+                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (!mem)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    Surface* surface = new (mem) Surface;
+
+    surface->window = pCreateInfo->window;
+
+    // TODO(jessehall): Create and use NATIVE_WINDOW_API_VULKAN.
+    int err =
+        native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
+              err);
+        surface->~Surface();
+        allocator->pfnFree(allocator->pUserData, surface);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    *out_surface = HandleFromSurface(surface);
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+void DestroySurfaceKHR(VkInstance instance,
+                       VkSurfaceKHR surface_handle,
+                       const VkAllocationCallbacks* allocator) {
+    Surface* surface = SurfaceFromHandle(surface_handle);
+    if (!surface)
+        return;
+    native_window_api_disconnect(surface->window.get(), NATIVE_WINDOW_API_EGL);
+    surface->~Surface();
+    if (!allocator)
+        allocator = &GetData(instance).allocator;
+    allocator->pfnFree(allocator->pUserData, surface);
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
+                                            uint32_t /*queue_family*/,
+                                            VkSurfaceKHR /*surface*/,
+                                            VkBool32* supported) {
+    *supported = VK_TRUE;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(
+    VkPhysicalDevice /*pdev*/,
+    VkSurfaceKHR surface,
+    VkSurfaceCapabilitiesKHR* capabilities) {
+    int err;
+    ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+
+    int width, height;
+    err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
+    if (err != 0) {
+        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
+    if (err != 0) {
+        ALOGE("NATIVE_WINDOW_DEFAULT_WIDTH query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    int transform_hint;
+    err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &transform_hint);
+    if (err != 0) {
+        ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // TODO(jessehall): Figure out what the min/max values should be.
+    capabilities->minImageCount = 2;
+    capabilities->maxImageCount = 3;
+
+    capabilities->currentExtent =
+        VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
+
+    // TODO(jessehall): Figure out what the max extent should be. Maximum
+    // texture dimension maybe?
+    capabilities->minImageExtent = VkExtent2D{1, 1};
+    capabilities->maxImageExtent = VkExtent2D{4096, 4096};
+
+    capabilities->maxImageArrayLayers = 1;
+
+    capabilities->supportedTransforms = kSupportedTransforms;
+    capabilities->currentTransform =
+        TranslateNativeToVulkanTransform(transform_hint);
+
+    // On Android, window composition is a WindowManager property, not something
+    // associated with the bufferqueue. It can't be changed from here.
+    capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+
+    // TODO(jessehall): I think these are right, but haven't thought hard about
+    // it. Do we need to query the driver for support of any of these?
+    // Currently not included:
+    // - VK_IMAGE_USAGE_GENERAL: maybe? does this imply cpu mappable?
+    // - VK_IMAGE_USAGE_DEPTH_STENCIL_BIT: definitely not
+    // - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT: definitely not
+    capabilities->supportedUsageFlags =
+        VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+        VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
+        VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
+
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice /*pdev*/,
+                                            VkSurfaceKHR /*surface*/,
+                                            uint32_t* count,
+                                            VkSurfaceFormatKHR* formats) {
+    // TODO(jessehall): Fill out the set of supported formats. Longer term, add
+    // a new gralloc method to query whether a (format, usage) pair is
+    // supported, and check that for each gralloc format that corresponds to a
+    // Vulkan format. Shorter term, just add a few more formats to the ones
+    // hardcoded below.
+
+    const VkSurfaceFormatKHR kFormats[] = {
+        {VK_FORMAT_R8G8B8A8_UNORM, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
+        {VK_FORMAT_R8G8B8A8_SRGB, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
+        {VK_FORMAT_R5G6B5_UNORM_PACK16, VK_COLORSPACE_SRGB_NONLINEAR_KHR},
+    };
+    const uint32_t kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
+
+    VkResult result = VK_SUCCESS;
+    if (formats) {
+        if (*count < kNumFormats)
+            result = VK_INCOMPLETE;
+        std::copy(kFormats, kFormats + std::min(*count, kNumFormats), formats);
+    }
+    *count = kNumFormats;
+    return result;
+}
+
+VKAPI_ATTR
+VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice /*pdev*/,
+                                                 VkSurfaceKHR /*surface*/,
+                                                 uint32_t* count,
+                                                 VkPresentModeKHR* modes) {
+    const VkPresentModeKHR kModes[] = {
+        VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_FIFO_KHR,
+    };
+    const uint32_t kNumModes = sizeof(kModes) / sizeof(kModes[0]);
+
+    VkResult result = VK_SUCCESS;
+    if (modes) {
+        if (*count < kNumModes)
+            result = VK_INCOMPLETE;
+        std::copy(kModes, kModes + std::min(*count, kNumModes), modes);
+    }
+    *count = kNumModes;
+    return result;
+}
+
+VKAPI_ATTR
+VkResult CreateSwapchainKHR(VkDevice device,
+                            const VkSwapchainCreateInfoKHR* create_info,
+                            const VkAllocationCallbacks* allocator,
+                            VkSwapchainKHR* swapchain_handle) {
+    int err;
+    VkResult result = VK_SUCCESS;
+
+    ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
+          " minImageCount=%u imageFormat=%u imageColorSpace=%u"
+          " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
+          " oldSwapchain=0x%" PRIx64,
+          reinterpret_cast<uint64_t>(create_info->surface),
+          create_info->minImageCount, create_info->imageFormat,
+          create_info->imageColorSpace, create_info->imageExtent.width,
+          create_info->imageExtent.height, create_info->imageUsage,
+          create_info->preTransform, create_info->presentMode,
+          reinterpret_cast<uint64_t>(create_info->oldSwapchain));
+
+    if (!allocator)
+        allocator = &GetData(device).allocator;
+
+    ALOGV_IF(create_info->imageArrayLayers != 1,
+             "Swapchain imageArrayLayers (%u) != 1 not supported",
+             create_info->imageArrayLayers);
+
+    ALOGE_IF(create_info->imageColorSpace != VK_COLORSPACE_SRGB_NONLINEAR_KHR,
+             "color spaces other than SRGB_NONLINEAR not yet implemented");
+    ALOGE_IF(create_info->oldSwapchain,
+             "swapchain re-creation not yet implemented");
+    ALOGE_IF((create_info->preTransform & ~kSupportedTransforms) != 0,
+             "swapchain preTransform %d not supported",
+             create_info->preTransform);
+    ALOGW_IF(!(create_info->presentMode == VK_PRESENT_MODE_FIFO_KHR ||
+               create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR),
+             "swapchain present mode %d not supported",
+             create_info->presentMode);
+
+    Surface& surface = *SurfaceFromHandle(create_info->surface);
+
+    // -- Reset the native window --
+    // The native window might have been used previously, and had its properties
+    // changed from defaults. That will affect the answer we get for queries
+    // like MIN_UNDEQUED_BUFFERS. Reset to a known/default state before we
+    // attempt such queries.
+
+    err = native_window_set_buffer_count(surface.window.get(), 0);
+    if (err != 0) {
+        ALOGE("native_window_set_buffer_count(0) failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    err = surface.window->setSwapInterval(surface.window.get(), 1);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window->setSwapInterval(1) failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // -- Configure the native window --
+
+    const auto& dispatch = GetData(device).driver;
+
+    int native_format = HAL_PIXEL_FORMAT_RGBA_8888;
+    switch (create_info->imageFormat) {
+        case VK_FORMAT_R8G8B8A8_UNORM:
+        case VK_FORMAT_R8G8B8A8_SRGB:
+            native_format = HAL_PIXEL_FORMAT_RGBA_8888;
+            break;
+        case VK_FORMAT_R5G6B5_UNORM_PACK16:
+            native_format = HAL_PIXEL_FORMAT_RGB_565;
+            break;
+        default:
+            ALOGE("unsupported swapchain format %d", create_info->imageFormat);
+            break;
+    }
+    err = native_window_set_buffers_format(surface.window.get(), native_format);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_buffers_format(%d) failed: %s (%d)",
+              native_format, strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    err = native_window_set_buffers_data_space(surface.window.get(),
+                                               HAL_DATASPACE_SRGB_LINEAR);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_buffers_data_space(%d) failed: %s (%d)",
+              HAL_DATASPACE_SRGB_LINEAR, strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    err = native_window_set_buffers_dimensions(
+        surface.window.get(), static_cast<int>(create_info->imageExtent.width),
+        static_cast<int>(create_info->imageExtent.height));
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
+              create_info->imageExtent.width, create_info->imageExtent.height,
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // VkSwapchainCreateInfo::preTransform indicates the transformation the app
+    // applied during rendering. native_window_set_transform() expects the
+    // inverse: the transform the app is requesting that the compositor perform
+    // during composition. With native windows, pre-transform works by rendering
+    // with the same transform the compositor is applying (as in Vulkan), but
+    // then requesting the inverse transform, so that when the compositor does
+    // it's job the two transforms cancel each other out and the compositor ends
+    // up applying an identity transform to the app's buffer.
+    err = native_window_set_buffers_transform(
+        surface.window.get(),
+        InvertTransformToNative(create_info->preTransform));
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
+              InvertTransformToNative(create_info->preTransform),
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    err = native_window_set_scaling_mode(
+        surface.window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_scaling_mode(SCALE_TO_WINDOW) failed: %s (%d)",
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    int query_value;
+    err = surface.window->query(surface.window.get(),
+                                NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
+                                &query_value);
+    if (err != 0 || query_value < 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err,
+              query_value);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+    uint32_t min_undequeued_buffers = static_cast<uint32_t>(query_value);
+    // The MIN_UNDEQUEUED_BUFFERS query doesn't know whether we'll be using
+    // async mode or not, and assumes not. But in async mode, the BufferQueue
+    // requires an extra undequeued buffer.
+    // See BufferQueueCore::getMinUndequeuedBufferCountLocked().
+    if (create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR)
+        min_undequeued_buffers += 1;
+
+    uint32_t num_images =
+        (create_info->minImageCount - 1) + min_undequeued_buffers;
+    err = native_window_set_buffer_count(surface.window.get(), num_images);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_buffer_count(%d) failed: %s (%d)", num_images,
+              strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    int gralloc_usage = 0;
+    // TODO(jessehall): Remove conditional once all drivers have been updated
+    if (dispatch.GetSwapchainGrallocUsageANDROID) {
+        result = dispatch.GetSwapchainGrallocUsageANDROID(
+            device, create_info->imageFormat, create_info->imageUsage,
+            &gralloc_usage);
+        if (result != VK_SUCCESS) {
+            ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+    } else {
+        gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+    }
+    err = native_window_set_usage(surface.window.get(), gralloc_usage);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    int swap_interval =
+        create_info->presentMode == VK_PRESENT_MODE_MAILBOX_KHR ? 0 : 1;
+    err = surface.window->setSwapInterval(surface.window.get(), swap_interval);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window->setSwapInterval(%d) failed: %s (%d)",
+              swap_interval, strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    // -- Allocate our Swapchain object --
+    // After this point, we must deallocate the swapchain on error.
+
+    void* mem = allocator->pfnAllocation(allocator->pUserData,
+                                         sizeof(Swapchain), alignof(Swapchain),
+                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+    if (!mem)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    Swapchain* swapchain = new (mem) Swapchain(surface, num_images);
+
+    // -- Dequeue all buffers and create a VkImage for each --
+    // Any failures during or after this must cancel the dequeued buffers.
+
+    VkNativeBufferANDROID image_native_buffer = {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wold-style-cast"
+        .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
+#pragma clang diagnostic pop
+        .pNext = nullptr,
+    };
+    VkImageCreateInfo image_create = {
+        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+        .pNext = &image_native_buffer,
+        .imageType = VK_IMAGE_TYPE_2D,
+        .format = create_info->imageFormat,
+        .extent = {0, 0, 1},
+        .mipLevels = 1,
+        .arrayLayers = 1,
+        .samples = VK_SAMPLE_COUNT_1_BIT,
+        .tiling = VK_IMAGE_TILING_OPTIMAL,
+        .usage = create_info->imageUsage,
+        .flags = 0,
+        .sharingMode = create_info->imageSharingMode,
+        .queueFamilyIndexCount = create_info->queueFamilyIndexCount,
+        .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
+    };
+
+    for (uint32_t i = 0; i < num_images; i++) {
+        Swapchain::Image& img = swapchain->images[i];
+
+        ANativeWindowBuffer* buffer;
+        err = surface.window->dequeueBuffer(surface.window.get(), &buffer,
+                                            &img.dequeue_fence);
+        if (err != 0) {
+            // TODO(jessehall): Improve error reporting. Can we enumerate
+            // possible errors and translate them to valid Vulkan result codes?
+            ALOGE("dequeueBuffer[%u] failed: %s (%d)", i, strerror(-err), err);
+            result = VK_ERROR_INITIALIZATION_FAILED;
+            break;
+        }
+        img.buffer = buffer;
+        img.dequeued = true;
+
+        image_create.extent =
+            VkExtent3D{static_cast<uint32_t>(img.buffer->width),
+                       static_cast<uint32_t>(img.buffer->height),
+                       1};
+        image_native_buffer.handle = img.buffer->handle;
+        image_native_buffer.stride = img.buffer->stride;
+        image_native_buffer.format = img.buffer->format;
+        image_native_buffer.usage = img.buffer->usage;
+
+        result =
+            dispatch.CreateImage(device, &image_create, nullptr, &img.image);
+        if (result != VK_SUCCESS) {
+            ALOGD("vkCreateImage w/ native buffer failed: %u", result);
+            break;
+        }
+    }
+
+    // -- Cancel all buffers, returning them to the queue --
+    // If an error occurred before, also destroy the VkImage and release the
+    // buffer reference. Otherwise, we retain a strong reference to the buffer.
+    //
+    // TODO(jessehall): The error path here is the same as DestroySwapchain,
+    // but not the non-error path. Should refactor/unify.
+    for (uint32_t i = 0; i < num_images; i++) {
+        Swapchain::Image& img = swapchain->images[i];
+        if (img.dequeued) {
+            surface.window->cancelBuffer(surface.window.get(), img.buffer.get(),
+                                         img.dequeue_fence);
+            img.dequeue_fence = -1;
+            img.dequeued = false;
+        }
+        if (result != VK_SUCCESS) {
+            if (img.image)
+                dispatch.DestroyImage(device, img.image, nullptr);
+        }
+    }
+
+    if (result != VK_SUCCESS) {
+        swapchain->~Swapchain();
+        allocator->pfnFree(allocator->pUserData, swapchain);
+        return result;
+    }
+
+    *swapchain_handle = HandleFromSwapchain(swapchain);
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+void DestroySwapchainKHR(VkDevice device,
+                         VkSwapchainKHR swapchain_handle,
+                         const VkAllocationCallbacks* allocator) {
+    const auto& dispatch = GetData(device).driver;
+    Swapchain* swapchain = SwapchainFromHandle(swapchain_handle);
+    const android::sp<ANativeWindow>& window = swapchain->surface.window;
+
+    for (uint32_t i = 0; i < swapchain->num_images; i++) {
+        Swapchain::Image& img = swapchain->images[i];
+        if (img.dequeued) {
+            window->cancelBuffer(window.get(), img.buffer.get(),
+                                 img.dequeue_fence);
+            img.dequeue_fence = -1;
+            img.dequeued = false;
+        }
+        if (img.image) {
+            dispatch.DestroyImage(device, img.image, nullptr);
+        }
+    }
+
+    if (!allocator)
+        allocator = &GetData(device).allocator;
+    swapchain->~Swapchain();
+    allocator->pfnFree(allocator->pUserData, swapchain);
+}
+
+VKAPI_ATTR
+VkResult GetSwapchainImagesKHR(VkDevice,
+                               VkSwapchainKHR swapchain_handle,
+                               uint32_t* count,
+                               VkImage* images) {
+    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+    VkResult result = VK_SUCCESS;
+    if (images) {
+        uint32_t n = swapchain.num_images;
+        if (*count < swapchain.num_images) {
+            n = *count;
+            result = VK_INCOMPLETE;
+        }
+        for (uint32_t i = 0; i < n; i++)
+            images[i] = swapchain.images[i].image;
+    }
+    *count = swapchain.num_images;
+    return result;
+}
+
+VKAPI_ATTR
+VkResult AcquireNextImageKHR(VkDevice device,
+                             VkSwapchainKHR swapchain_handle,
+                             uint64_t timeout,
+                             VkSemaphore semaphore,
+                             VkFence vk_fence,
+                             uint32_t* image_index) {
+    Swapchain& swapchain = *SwapchainFromHandle(swapchain_handle);
+    ANativeWindow* window = swapchain.surface.window.get();
+    VkResult result;
+    int err;
+
+    ALOGW_IF(
+        timeout != UINT64_MAX,
+        "vkAcquireNextImageKHR: non-infinite timeouts not yet implemented");
+
+    ANativeWindowBuffer* buffer;
+    int fence_fd;
+    err = window->dequeueBuffer(window, &buffer, &fence_fd);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
+
+    uint32_t idx;
+    for (idx = 0; idx < swapchain.num_images; idx++) {
+        if (swapchain.images[idx].buffer.get() == buffer) {
+            swapchain.images[idx].dequeued = true;
+            swapchain.images[idx].dequeue_fence = fence_fd;
+            break;
+        }
+    }
+    if (idx == swapchain.num_images) {
+        ALOGE("dequeueBuffer returned unrecognized buffer");
+        window->cancelBuffer(window, buffer, fence_fd);
+        return VK_ERROR_OUT_OF_DATE_KHR;
+    }
+
+    int fence_clone = -1;
+    if (fence_fd != -1) {
+        fence_clone = dup(fence_fd);
+        if (fence_clone == -1) {
+            ALOGE("dup(fence) failed, stalling until signalled: %s (%d)",
+                  strerror(errno), errno);
+            sync_wait(fence_fd, -1 /* forever */);
+        }
+    }
+
+    result = GetData(device).driver.AcquireImageANDROID(
+        device, swapchain.images[idx].image, fence_clone, semaphore, vk_fence);
+    if (result != VK_SUCCESS) {
+        // NOTE: we're relying on AcquireImageANDROID to close fence_clone,
+        // even if the call fails. We could close it ourselves on failure, but
+        // that would create a race condition if the driver closes it on a
+        // failure path: some other thread might create an fd with the same
+        // number between the time the driver closes it and the time we close
+        // it. We must assume one of: the driver *always* closes it even on
+        // failure, or *never* closes it on failure.
+        window->cancelBuffer(window, buffer, fence_fd);
+        swapchain.images[idx].dequeued = false;
+        swapchain.images[idx].dequeue_fence = -1;
+        return result;
+    }
+
+    *image_index = idx;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info) {
+    ALOGV_IF(present_info->sType != VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+             "vkQueuePresentKHR: invalid VkPresentInfoKHR structure type %d",
+             present_info->sType);
+    ALOGV_IF(present_info->pNext, "VkPresentInfo::pNext != NULL");
+
+    const auto& dispatch = GetData(queue).driver;
+    VkResult final_result = VK_SUCCESS;
+    for (uint32_t sc = 0; sc < present_info->swapchainCount; sc++) {
+        Swapchain& swapchain =
+            *SwapchainFromHandle(present_info->pSwapchains[sc]);
+        ANativeWindow* window = swapchain.surface.window.get();
+        uint32_t image_idx = present_info->pImageIndices[sc];
+        Swapchain::Image& img = swapchain.images[image_idx];
+        VkResult result;
+        int err;
+
+        int fence = -1;
+        result = dispatch.QueueSignalReleaseImageANDROID(
+            queue, present_info->waitSemaphoreCount,
+            present_info->pWaitSemaphores, img.image, &fence);
+        if (result != VK_SUCCESS) {
+            ALOGE("QueueSignalReleaseImageANDROID failed: %d", result);
+            if (present_info->pResults)
+                present_info->pResults[sc] = result;
+            if (final_result == VK_SUCCESS)
+                final_result = result;
+            // TODO(jessehall): What happens to the buffer here? Does the app
+            // still own it or not, i.e. should we cancel the buffer? Hard to
+            // do correctly without synchronizing, though I guess we could wait
+            // for the queue to idle.
+            continue;
+        }
+
+        err = window->queueBuffer(window, img.buffer.get(), fence);
+        if (err != 0) {
+            // TODO(jessehall): What now? We should probably cancel the buffer,
+            // I guess?
+            ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
+            if (present_info->pResults)
+                present_info->pResults[sc] = result;
+            if (final_result == VK_SUCCESS)
+                final_result = VK_ERROR_INITIALIZATION_FAILED;
+            continue;
+        }
+
+        if (img.dequeue_fence != -1) {
+            close(img.dequeue_fence);
+            img.dequeue_fence = -1;
+        }
+        img.dequeued = false;
+
+        if (present_info->pResults)
+            present_info->pResults[sc] = VK_SUCCESS;
+    }
+
+    return final_result;
+}
+
+}  // namespace driver
+}  // namespace vulkan
diff --git a/vulkan/libvulkan/swapchain.h b/vulkan/libvulkan/swapchain.h
new file mode 100644
index 0000000..2c60c49
--- /dev/null
+++ b/vulkan/libvulkan/swapchain.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef LIBVULKAN_SWAPCHAIN_H
+#define LIBVULKAN_SWAPCHAIN_H 1
+
+#include <vulkan/vulkan.h>
+
+namespace vulkan {
+namespace driver {
+
+// clang-format off
+VKAPI_ATTR VkResult CreateAndroidSurfaceKHR(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+VKAPI_ATTR void DestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks* allocator);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice pdev, uint32_t queue_family, VkSurfaceKHR surface, VkBool32* pSupported);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR* capabilities);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkSurfaceFormatKHR* formats);
+VKAPI_ATTR VkResult GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice pdev, VkSurfaceKHR surface, uint32_t* count, VkPresentModeKHR* modes);
+VKAPI_ATTR VkResult CreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR* create_info, const VkAllocationCallbacks* allocator, VkSwapchainKHR* swapchain_handle);
+VKAPI_ATTR void DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain_handle, const VkAllocationCallbacks* allocator);
+VKAPI_ATTR VkResult GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint32_t* count, VkImage* images);
+VKAPI_ATTR VkResult AcquireNextImageKHR(VkDevice device, VkSwapchainKHR swapchain_handle, uint64_t timeout, VkSemaphore semaphore, VkFence fence, uint32_t* image_index);
+VKAPI_ATTR VkResult QueuePresentKHR(VkQueue queue, const VkPresentInfoKHR* present_info);
+// clang-format on
+
+}  // namespace driver
+}  // namespace vulkan
+
+#endif  // LIBVULKAN_SWAPCHAIN_H
diff --git a/opengl/libs/GLES_trace/src/gltrace_hooks.h b/vulkan/libvulkan/vulkan_loader_data.cpp
similarity index 64%
rename from opengl/libs/GLES_trace/src/gltrace_hooks.h
rename to vulkan/libvulkan/vulkan_loader_data.cpp
index c946a09..a6a0295 100644
--- a/opengl/libs/GLES_trace/src/gltrace_hooks.h
+++ b/vulkan/libvulkan/vulkan_loader_data.cpp
@@ -1,11 +1,11 @@
 /*
- * Copyright 2011, The Android Open Source Project
+ * Copyright 2015 The Android Open Source Project
  *
  * 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
+ *      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,
@@ -14,19 +14,11 @@
  * limitations under the License.
  */
 
-#ifndef __GLD_HOOKS_H_
-#define __GLD_HOOKS_H_
+#include <vulkan/vulkan_loader_data.h>
 
-#include "hooks.h"
+using namespace vulkan;
 
-namespace android {
-namespace gltrace {
-
-using ::android::gl_hooks_t;
-
-gl_hooks_t *getGLHooks();
-
-};
-};
-
-#endif
+LoaderData& LoaderData::GetInstance() {
+    static LoaderData loader_data;
+    return loader_data;
+}
diff --git a/vulkan/nulldrv/Android.mk b/vulkan/nulldrv/Android.mk
new file mode 100644
index 0000000..77d4746
--- /dev/null
+++ b/vulkan/nulldrv/Android.mk
@@ -0,0 +1,45 @@
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing \
+	-DLOG_TAG=\"vknulldrv\" \
+	-Weverything -Werror \
+	-Wno-padded \
+	-Wno-undef \
+	-Wno-zero-length-array
+#LOCAL_CFLAGS += -DLOG_NDEBUG=0
+LOCAL_CPPFLAGS := -std=c++1y \
+	-Wno-c++98-compat-pedantic \
+	-Wno-c99-extensions
+
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include
+
+LOCAL_SRC_FILES := \
+	null_driver.cpp \
+	null_driver_gen.cpp
+
+LOCAL_SHARED_LIBRARIES := liblog
+
+# Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM)
+LOCAL_MODULE := vulkan.default
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
new file mode 100644
index 0000000..f29cb68
--- /dev/null
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -0,0 +1,1406 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 <hardware/hwvulkan.h>
+
+#include <algorithm>
+#include <array>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <log/log.h>
+#include <utils/Errors.h>
+
+#include "null_driver_gen.h"
+
+using namespace null_driver;
+
+struct VkPhysicalDevice_T {
+    hwvulkan_dispatch_t dispatch;
+};
+
+struct VkInstance_T {
+    hwvulkan_dispatch_t dispatch;
+    VkAllocationCallbacks allocator;
+    VkPhysicalDevice_T physical_device;
+    uint64_t next_callback_handle;
+};
+
+struct VkQueue_T {
+    hwvulkan_dispatch_t dispatch;
+};
+
+struct VkCommandBuffer_T {
+    hwvulkan_dispatch_t dispatch;
+};
+
+namespace {
+// Handles for non-dispatchable objects are either pointers, or arbitrary
+// 64-bit non-zero values. We only use pointers when we need to keep state for
+// the object even in a null driver. For the rest, we form a handle as:
+//   [63:63] = 1 to distinguish from pointer handles*
+//   [62:56] = non-zero handle type enum value
+//   [55: 0] = per-handle-type incrementing counter
+// * This works because virtual addresses with the high bit set are reserved
+// for kernel data in all ABIs we run on.
+//
+// We never reclaim handles on vkDestroy*. It's not even necessary for us to
+// have distinct handles for live objects, and practically speaking we won't
+// ever create 2^56 objects of the same type from a single VkDevice in a null
+// driver.
+//
+// Using a namespace here instead of 'enum class' since we want scoped
+// constants but also want implicit conversions to integral types.
+namespace HandleType {
+enum Enum {
+    kBufferView,
+    kDebugReportCallbackEXT,
+    kDescriptorPool,
+    kDescriptorSet,
+    kDescriptorSetLayout,
+    kEvent,
+    kFence,
+    kFramebuffer,
+    kImageView,
+    kPipeline,
+    kPipelineCache,
+    kPipelineLayout,
+    kQueryPool,
+    kRenderPass,
+    kSampler,
+    kSemaphore,
+    kShaderModule,
+
+    kNumTypes
+};
+}  // namespace HandleType
+
+const VkDeviceSize kMaxDeviceMemory = 0x10000000;  // 256 MiB, arbitrary
+
+}  // anonymous namespace
+
+struct VkDevice_T {
+    hwvulkan_dispatch_t dispatch;
+    VkAllocationCallbacks allocator;
+    VkInstance_T* instance;
+    VkQueue_T queue;
+    std::array<uint64_t, HandleType::kNumTypes> next_handle;
+};
+
+// -----------------------------------------------------------------------------
+// Declare HAL_MODULE_INFO_SYM early so it can be referenced by nulldrv_device
+// later.
+
+namespace {
+int OpenDevice(const hw_module_t* module, const char* id, hw_device_t** device);
+hw_module_methods_t nulldrv_module_methods = {.open = OpenDevice};
+}  // namespace
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-variable-declarations"
+__attribute__((visibility("default"))) hwvulkan_module_t HAL_MODULE_INFO_SYM = {
+    .common =
+        {
+            .tag = HARDWARE_MODULE_TAG,
+            .module_api_version = HWVULKAN_MODULE_API_VERSION_0_1,
+            .hal_api_version = HARDWARE_HAL_API_VERSION,
+            .id = HWVULKAN_HARDWARE_MODULE_ID,
+            .name = "Null Vulkan Driver",
+            .author = "The Android Open Source Project",
+            .methods = &nulldrv_module_methods,
+        },
+};
+#pragma clang diagnostic pop
+
+// -----------------------------------------------------------------------------
+
+namespace {
+
+int CloseDevice(struct hw_device_t* /*device*/) {
+    // nothing to do - opening a device doesn't allocate any resources
+    return 0;
+}
+
+hwvulkan_device_t nulldrv_device = {
+    .common =
+        {
+            .tag = HARDWARE_DEVICE_TAG,
+            .version = HWVULKAN_DEVICE_API_VERSION_0_1,
+            .module = &HAL_MODULE_INFO_SYM.common,
+            .close = CloseDevice,
+        },
+    .EnumerateInstanceExtensionProperties =
+        EnumerateInstanceExtensionProperties,
+    .CreateInstance = CreateInstance,
+    .GetInstanceProcAddr = GetInstanceProcAddr};
+
+int OpenDevice(const hw_module_t* /*module*/,
+               const char* id,
+               hw_device_t** device) {
+    if (strcmp(id, HWVULKAN_DEVICE_0) == 0) {
+        *device = &nulldrv_device.common;
+        return 0;
+    }
+    return -ENOENT;
+}
+
+VkInstance_T* GetInstanceFromPhysicalDevice(
+    VkPhysicalDevice_T* physical_device) {
+    return reinterpret_cast<VkInstance_T*>(
+        reinterpret_cast<uintptr_t>(physical_device) -
+        offsetof(VkInstance_T, physical_device));
+}
+
+uint64_t AllocHandle(uint64_t type, uint64_t* next_handle) {
+    const uint64_t kHandleMask = (UINT64_C(1) << 56) - 1;
+    ALOGE_IF(*next_handle == kHandleMask,
+             "non-dispatchable handles of type=%" PRIu64
+             " are about to overflow",
+             type);
+    return (UINT64_C(1) << 63) | ((type & 0x7) << 56) |
+           ((*next_handle)++ & kHandleMask);
+}
+
+template <class Handle>
+Handle AllocHandle(VkInstance instance, HandleType::Enum type) {
+    return reinterpret_cast<Handle>(
+        AllocHandle(type, &instance->next_callback_handle));
+}
+
+template <class Handle>
+Handle AllocHandle(VkDevice device, HandleType::Enum type) {
+    return reinterpret_cast<Handle>(
+        AllocHandle(type, &device->next_handle[type]));
+}
+
+VKAPI_ATTR void* DefaultAllocate(void*,
+                                 size_t size,
+                                 size_t alignment,
+                                 VkSystemAllocationScope) {
+    void* ptr = nullptr;
+    // Vulkan requires 'alignment' to be a power of two, but posix_memalign
+    // additionally requires that it be at least sizeof(void*).
+    int ret = posix_memalign(&ptr, std::max(alignment, sizeof(void*)), size);
+    return ret == 0 ? ptr : nullptr;
+}
+
+VKAPI_ATTR void* DefaultReallocate(void*,
+                                   void* ptr,
+                                   size_t size,
+                                   size_t alignment,
+                                   VkSystemAllocationScope) {
+    if (size == 0) {
+        free(ptr);
+        return nullptr;
+    }
+
+    // TODO(jessehall): Right now we never shrink allocations; if the new
+    // request is smaller than the existing chunk, we just continue using it.
+    // The null driver never reallocs, so this doesn't matter. If that changes,
+    // or if this code is copied into some other project, this should probably
+    // have a heuristic to allocate-copy-free when doing so will save "enough"
+    // space.
+    size_t old_size = ptr ? malloc_usable_size(ptr) : 0;
+    if (size <= old_size)
+        return ptr;
+
+    void* new_ptr = nullptr;
+    if (posix_memalign(&new_ptr, std::max(alignment, sizeof(void*)), size) != 0)
+        return nullptr;
+    if (ptr) {
+        memcpy(new_ptr, ptr, std::min(old_size, size));
+        free(ptr);
+    }
+    return new_ptr;
+}
+
+VKAPI_ATTR void DefaultFree(void*, void* ptr) {
+    free(ptr);
+}
+
+const VkAllocationCallbacks kDefaultAllocCallbacks = {
+    .pUserData = nullptr,
+    .pfnAllocation = DefaultAllocate,
+    .pfnReallocation = DefaultReallocate,
+    .pfnFree = DefaultFree,
+};
+
+}  // namespace
+
+namespace null_driver {
+
+#define DEFINE_OBJECT_HANDLE_CONVERSION(T)              \
+    T* Get##T##FromHandle(Vk##T h);                     \
+    T* Get##T##FromHandle(Vk##T h) {                    \
+        return reinterpret_cast<T*>(uintptr_t(h));      \
+    }                                                   \
+    Vk##T GetHandleTo##T(const T* obj);                 \
+    Vk##T GetHandleTo##T(const T* obj) {                \
+        return Vk##T(reinterpret_cast<uintptr_t>(obj)); \
+    }
+
+// -----------------------------------------------------------------------------
+// Global
+
+VKAPI_ATTR
+VkResult EnumerateInstanceExtensionProperties(
+    const char* layer_name,
+    uint32_t* count,
+    VkExtensionProperties* properties) {
+    if (layer_name) {
+        ALOGW(
+            "Driver vkEnumerateInstanceExtensionProperties shouldn't be called "
+            "with a layer name ('%s')",
+            layer_name);
+    }
+
+// NOTE: Change this to zero to report and extension, which can be useful
+// for testing changes to the loader.
+#if 1
+    (void)properties;  // unused
+    *count = 0;
+    return VK_SUCCESS;
+#else
+    const VkExtensionProperties kExtensions[] = {
+        {VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
+    const uint32_t kExtensionsCount =
+        sizeof(kExtensions) / sizeof(kExtensions[0]);
+
+    if (!properties || *count > kExtensionsCount)
+        *count = kExtensionsCount;
+    if (properties)
+        std::copy(kExtensions, kExtensions + *count, properties);
+    return *count < kExtensionsCount ? VK_INCOMPLETE : VK_SUCCESS;
+#endif
+}
+
+VKAPI_ATTR
+VkResult CreateInstance(const VkInstanceCreateInfo* create_info,
+                        const VkAllocationCallbacks* allocator,
+                        VkInstance* out_instance) {
+    if (!allocator)
+        allocator = &kDefaultAllocCallbacks;
+
+    VkInstance_T* instance =
+        static_cast<VkInstance_T*>(allocator->pfnAllocation(
+            allocator->pUserData, sizeof(VkInstance_T), alignof(VkInstance_T),
+            VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE));
+    if (!instance)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    instance->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    instance->allocator = *allocator;
+    instance->physical_device.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    instance->next_callback_handle = 0;
+
+    for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
+        if (strcmp(create_info->ppEnabledExtensionNames[i],
+                   VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
+            ALOGV("instance extension '%s' requested",
+                  create_info->ppEnabledExtensionNames[i]);
+        } else {
+            ALOGW("unsupported extension '%s' requested",
+                  create_info->ppEnabledExtensionNames[i]);
+        }
+    }
+
+    *out_instance = instance;
+    return VK_SUCCESS;
+}
+
+VKAPI_ATTR
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name) {
+    return instance ? GetInstanceProcAddr(name) : GetGlobalProcAddr(name);
+}
+
+VKAPI_ATTR
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice, const char* name) {
+    return GetInstanceProcAddr(name);
+}
+
+// -----------------------------------------------------------------------------
+// Instance
+
+void DestroyInstance(VkInstance instance,
+                     const VkAllocationCallbacks* /*allocator*/) {
+    instance->allocator.pfnFree(instance->allocator.pUserData, instance);
+}
+
+// -----------------------------------------------------------------------------
+// PhysicalDevice
+
+VkResult EnumeratePhysicalDevices(VkInstance instance,
+                                  uint32_t* physical_device_count,
+                                  VkPhysicalDevice* physical_devices) {
+    if (physical_devices && *physical_device_count >= 1)
+        physical_devices[0] = &instance->physical_device;
+    *physical_device_count = 1;
+    return VK_SUCCESS;
+}
+
+VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice /*gpu*/,
+                                        uint32_t* count,
+                                        VkLayerProperties* /*properties*/) {
+    ALOGW("Driver vkEnumerateDeviceLayerProperties shouldn't be called");
+    *count = 0;
+    return VK_SUCCESS;
+}
+
+VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice /*gpu*/,
+                                            const char* layer_name,
+                                            uint32_t* count,
+                                            VkExtensionProperties* properties) {
+    if (layer_name) {
+        ALOGW(
+            "Driver vkEnumerateDeviceExtensionProperties shouldn't be called "
+            "with a layer name ('%s')",
+            layer_name);
+        *count = 0;
+        return VK_SUCCESS;
+    }
+
+    const VkExtensionProperties kExtensions[] = {
+        {VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME,
+         VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION}};
+    const uint32_t kExtensionsCount =
+        sizeof(kExtensions) / sizeof(kExtensions[0]);
+
+    if (!properties || *count > kExtensionsCount)
+        *count = kExtensionsCount;
+    if (properties)
+        std::copy(kExtensions, kExtensions + *count, properties);
+    return *count < kExtensionsCount ? VK_INCOMPLETE : VK_SUCCESS;
+}
+
+void GetPhysicalDeviceProperties(VkPhysicalDevice,
+                                 VkPhysicalDeviceProperties* properties) {
+    properties->apiVersion = VK_API_VERSION;
+    properties->driverVersion = VK_MAKE_VERSION(0, 0, 1);
+    properties->vendorID = 0;
+    properties->deviceID = 0;
+    properties->deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
+    strcpy(properties->deviceName, "Android Vulkan Null Driver");
+    memset(properties->pipelineCacheUUID, 0,
+           sizeof(properties->pipelineCacheUUID));
+    properties->limits = VkPhysicalDeviceLimits{
+        4096,     // maxImageDimension1D
+        4096,     // maxImageDimension2D
+        256,      // maxImageDimension3D
+        4096,     // maxImageDimensionCube
+        256,      // maxImageArrayLayers
+        65536,    // maxTexelBufferElements
+        16384,    // maxUniformBufferRange
+        1 << 27,  // maxStorageBufferRange
+        128,      // maxPushConstantsSize
+        4096,     // maxMemoryAllocationCount
+        4000,     // maxSamplerAllocationCount
+        1,        // bufferImageGranularity
+        0,        // sparseAddressSpaceSize
+        4,        // maxBoundDescriptorSets
+        16,       // maxPerStageDescriptorSamplers
+        12,       // maxPerStageDescriptorUniformBuffers
+        4,        // maxPerStageDescriptorStorageBuffers
+        16,       // maxPerStageDescriptorSampledImages
+        4,        // maxPerStageDescriptorStorageImages
+        4,        // maxPerStageDescriptorInputAttachments
+        128,      // maxPerStageResources
+        96,       // maxDescriptorSetSamplers
+        72,       // maxDescriptorSetUniformBuffers
+        8,        // maxDescriptorSetUniformBuffersDynamic
+        24,       // maxDescriptorSetStorageBuffers
+        4,        // maxDescriptorSetStorageBuffersDynamic
+        96,       // maxDescriptorSetSampledImages
+        24,       // maxDescriptorSetStorageImages
+        4,        // maxDescriptorSetInputAttachments
+        16,       // maxVertexInputAttributes
+        16,       // maxVertexInputBindings
+        2047,     // maxVertexInputAttributeOffset
+        2048,     // maxVertexInputBindingStride
+        64,       // maxVertexOutputComponents
+        0,        // maxTessellationGenerationLevel
+        0,        // maxTessellationPatchSize
+        0,        // maxTessellationControlPerVertexInputComponents
+        0,        // maxTessellationControlPerVertexOutputComponents
+        0,        // maxTessellationControlPerPatchOutputComponents
+        0,        // maxTessellationControlTotalOutputComponents
+        0,        // maxTessellationEvaluationInputComponents
+        0,        // maxTessellationEvaluationOutputComponents
+        0,        // maxGeometryShaderInvocations
+        0,        // maxGeometryInputComponents
+        0,        // maxGeometryOutputComponents
+        0,        // maxGeometryOutputVertices
+        0,        // maxGeometryTotalOutputComponents
+        64,       // maxFragmentInputComponents
+        4,        // maxFragmentOutputAttachments
+        0,        // maxFragmentDualSrcAttachments
+        4,        // maxFragmentCombinedOutputResources
+        16384,    // maxComputeSharedMemorySize
+        {65536, 65536, 65536},  // maxComputeWorkGroupCount[3]
+        128,                    // maxComputeWorkGroupInvocations
+        {128, 128, 64},         // maxComputeWorkGroupSize[3]
+        4,                      // subPixelPrecisionBits
+        4,                      // subTexelPrecisionBits
+        4,                      // mipmapPrecisionBits
+        UINT32_MAX,             // maxDrawIndexedIndexValue
+        1,                      // maxDrawIndirectCount
+        2,                      // maxSamplerLodBias
+        1,                      // maxSamplerAnisotropy
+        1,                      // maxViewports
+        {4096, 4096},           // maxViewportDimensions[2]
+        {-8192.0f, 8191.0f},    // viewportBoundsRange[2]
+        0,                      // viewportSubPixelBits
+        64,                     // minMemoryMapAlignment
+        256,                    // minTexelBufferOffsetAlignment
+        256,                    // minUniformBufferOffsetAlignment
+        256,                    // minStorageBufferOffsetAlignment
+        -8,                     // minTexelOffset
+        7,                      // maxTexelOffset
+        0,                      // minTexelGatherOffset
+        0,                      // maxTexelGatherOffset
+        0.0f,                   // minInterpolationOffset
+        0.0f,                   // maxInterpolationOffset
+        0,                      // subPixelInterpolationOffsetBits
+        4096,                   // maxFramebufferWidth
+        4096,                   // maxFramebufferHeight
+        256,                    // maxFramebufferLayers
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // framebufferColorSampleCounts
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // framebufferDepthSampleCounts
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // framebufferStencilSampleCounts
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // framebufferNoAttachmentsSampleCounts
+        4,                          // maxColorAttachments
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // sampledImageColorSampleCounts
+        VK_SAMPLE_COUNT_1_BIT,      // sampledImageIntegerSampleCounts
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // sampledImageDepthSampleCounts
+        VK_SAMPLE_COUNT_1_BIT |
+            VK_SAMPLE_COUNT_4_BIT,  // sampledImageStencilSampleCounts
+        VK_SAMPLE_COUNT_1_BIT,      // storageImageSampleCounts
+        1,                          // maxSampleMaskWords
+        VK_TRUE,                    // timestampComputeAndGraphics
+        1,                          // timestampPeriod
+        0,                          // maxClipDistances
+        0,                          // maxCullDistances
+        0,                          // maxCombinedClipAndCullDistances
+        2,                          // discreteQueuePriorities
+        {1.0f, 1.0f},               // pointSizeRange[2]
+        {1.0f, 1.0f},               // lineWidthRange[2]
+        0.0f,                       // pointSizeGranularity
+        0.0f,                       // lineWidthGranularity
+        VK_TRUE,                    // strictLines
+        VK_TRUE,                    // standardSampleLocations
+        1,                          // optimalBufferCopyOffsetAlignment
+        1,                          // optimalBufferCopyRowPitchAlignment
+        64,                         // nonCoherentAtomSize
+    };
+}
+
+void GetPhysicalDeviceQueueFamilyProperties(
+    VkPhysicalDevice,
+    uint32_t* count,
+    VkQueueFamilyProperties* properties) {
+    if (!properties || *count > 1)
+        *count = 1;
+    if (properties && *count == 1) {
+        properties->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT |
+                                 VK_QUEUE_TRANSFER_BIT;
+        properties->queueCount = 1;
+        properties->timestampValidBits = 64;
+        properties->minImageTransferGranularity = VkExtent3D{1, 1, 1};
+    }
+}
+
+void GetPhysicalDeviceMemoryProperties(
+    VkPhysicalDevice,
+    VkPhysicalDeviceMemoryProperties* properties) {
+    properties->memoryTypeCount = 1;
+    properties->memoryTypes[0].propertyFlags =
+        VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+        VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+        VK_MEMORY_PROPERTY_HOST_COHERENT_BIT |
+        VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
+    properties->memoryTypes[0].heapIndex = 0;
+    properties->memoryHeapCount = 1;
+    properties->memoryHeaps[0].size = kMaxDeviceMemory;
+    properties->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
+}
+
+void GetPhysicalDeviceFeatures(VkPhysicalDevice /*gpu*/,
+                               VkPhysicalDeviceFeatures* features) {
+    *features = VkPhysicalDeviceFeatures{
+        VK_TRUE,   // robustBufferAccess
+        VK_FALSE,  // fullDrawIndexUint32
+        VK_FALSE,  // imageCubeArray
+        VK_FALSE,  // independentBlend
+        VK_FALSE,  // geometryShader
+        VK_FALSE,  // tessellationShader
+        VK_FALSE,  // sampleRateShading
+        VK_FALSE,  // dualSrcBlend
+        VK_FALSE,  // logicOp
+        VK_FALSE,  // multiDrawIndirect
+        VK_FALSE,  // drawIndirectFirstInstance
+        VK_FALSE,  // depthClamp
+        VK_FALSE,  // depthBiasClamp
+        VK_FALSE,  // fillModeNonSolid
+        VK_FALSE,  // depthBounds
+        VK_FALSE,  // wideLines
+        VK_FALSE,  // largePoints
+        VK_FALSE,  // alphaToOne
+        VK_FALSE,  // multiViewport
+        VK_FALSE,  // samplerAnisotropy
+        VK_FALSE,  // textureCompressionETC2
+        VK_FALSE,  // textureCompressionASTC_LDR
+        VK_FALSE,  // textureCompressionBC
+        VK_FALSE,  // occlusionQueryPrecise
+        VK_FALSE,  // pipelineStatisticsQuery
+        VK_FALSE,  // vertexPipelineStoresAndAtomics
+        VK_FALSE,  // fragmentStoresAndAtomics
+        VK_FALSE,  // shaderTessellationAndGeometryPointSize
+        VK_FALSE,  // shaderImageGatherExtended
+        VK_FALSE,  // shaderStorageImageExtendedFormats
+        VK_FALSE,  // shaderStorageImageMultisample
+        VK_FALSE,  // shaderStorageImageReadWithoutFormat
+        VK_FALSE,  // shaderStorageImageWriteWithoutFormat
+        VK_FALSE,  // shaderUniformBufferArrayDynamicIndexing
+        VK_FALSE,  // shaderSampledImageArrayDynamicIndexing
+        VK_FALSE,  // shaderStorageBufferArrayDynamicIndexing
+        VK_FALSE,  // shaderStorageImageArrayDynamicIndexing
+        VK_FALSE,  // shaderClipDistance
+        VK_FALSE,  // shaderCullDistance
+        VK_FALSE,  // shaderFloat64
+        VK_FALSE,  // shaderInt64
+        VK_FALSE,  // shaderInt16
+        VK_FALSE,  // shaderResourceResidency
+        VK_FALSE,  // shaderResourceMinLod
+        VK_FALSE,  // sparseBinding
+        VK_FALSE,  // sparseResidencyBuffer
+        VK_FALSE,  // sparseResidencyImage2D
+        VK_FALSE,  // sparseResidencyImage3D
+        VK_FALSE,  // sparseResidency2Samples
+        VK_FALSE,  // sparseResidency4Samples
+        VK_FALSE,  // sparseResidency8Samples
+        VK_FALSE,  // sparseResidency16Samples
+        VK_FALSE,  // sparseResidencyAliased
+        VK_FALSE,  // variableMultisampleRate
+        VK_FALSE,  // inheritedQueries
+    };
+}
+
+// -----------------------------------------------------------------------------
+// Device
+
+VkResult CreateDevice(VkPhysicalDevice physical_device,
+                      const VkDeviceCreateInfo* create_info,
+                      const VkAllocationCallbacks* allocator,
+                      VkDevice* out_device) {
+    VkInstance_T* instance = GetInstanceFromPhysicalDevice(physical_device);
+    if (!allocator)
+        allocator = &instance->allocator;
+    VkDevice_T* device = static_cast<VkDevice_T*>(allocator->pfnAllocation(
+        allocator->pUserData, sizeof(VkDevice_T), alignof(VkDevice_T),
+        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE));
+    if (!device)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+    device->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    device->allocator = *allocator;
+    device->instance = instance;
+    device->queue.dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    std::fill(device->next_handle.begin(), device->next_handle.end(),
+              UINT64_C(0));
+
+    for (uint32_t i = 0; i < create_info->enabledExtensionCount; i++) {
+        if (strcmp(create_info->ppEnabledExtensionNames[i],
+                   VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME) == 0) {
+            ALOGV("Enabling " VK_ANDROID_NATIVE_BUFFER_EXTENSION_NAME);
+        }
+    }
+
+    *out_device = device;
+    return VK_SUCCESS;
+}
+
+void DestroyDevice(VkDevice device,
+                   const VkAllocationCallbacks* /*allocator*/) {
+    if (!device)
+        return;
+    device->allocator.pfnFree(device->allocator.pUserData, device);
+}
+
+void GetDeviceQueue(VkDevice device, uint32_t, uint32_t, VkQueue* queue) {
+    *queue = &device->queue;
+}
+
+// -----------------------------------------------------------------------------
+// CommandPool
+
+struct CommandPool {
+    typedef VkCommandPool HandleType;
+    VkAllocationCallbacks allocator;
+};
+DEFINE_OBJECT_HANDLE_CONVERSION(CommandPool)
+
+VkResult CreateCommandPool(VkDevice device,
+                           const VkCommandPoolCreateInfo* /*create_info*/,
+                           const VkAllocationCallbacks* allocator,
+                           VkCommandPool* cmd_pool) {
+    if (!allocator)
+        allocator = &device->allocator;
+    CommandPool* pool = static_cast<CommandPool*>(allocator->pfnAllocation(
+        allocator->pUserData, sizeof(CommandPool), alignof(CommandPool),
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+    if (!pool)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    pool->allocator = *allocator;
+    *cmd_pool = GetHandleToCommandPool(pool);
+    return VK_SUCCESS;
+}
+
+void DestroyCommandPool(VkDevice /*device*/,
+                        VkCommandPool cmd_pool,
+                        const VkAllocationCallbacks* /*allocator*/) {
+    CommandPool* pool = GetCommandPoolFromHandle(cmd_pool);
+    pool->allocator.pfnFree(pool->allocator.pUserData, pool);
+}
+
+// -----------------------------------------------------------------------------
+// CmdBuffer
+
+VkResult AllocateCommandBuffers(VkDevice /*device*/,
+                                const VkCommandBufferAllocateInfo* alloc_info,
+                                VkCommandBuffer* cmdbufs) {
+    VkResult result = VK_SUCCESS;
+    CommandPool& pool = *GetCommandPoolFromHandle(alloc_info->commandPool);
+    std::fill(cmdbufs, cmdbufs + alloc_info->commandBufferCount, nullptr);
+    for (uint32_t i = 0; i < alloc_info->commandBufferCount; i++) {
+        cmdbufs[i] =
+            static_cast<VkCommandBuffer_T*>(pool.allocator.pfnAllocation(
+                pool.allocator.pUserData, sizeof(VkCommandBuffer_T),
+                alignof(VkCommandBuffer_T), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+        if (!cmdbufs[i]) {
+            result = VK_ERROR_OUT_OF_HOST_MEMORY;
+            break;
+        }
+        cmdbufs[i]->dispatch.magic = HWVULKAN_DISPATCH_MAGIC;
+    }
+    if (result != VK_SUCCESS) {
+        for (uint32_t i = 0; i < alloc_info->commandBufferCount; i++) {
+            if (!cmdbufs[i])
+                break;
+            pool.allocator.pfnFree(pool.allocator.pUserData, cmdbufs[i]);
+        }
+    }
+    return result;
+}
+
+void FreeCommandBuffers(VkDevice /*device*/,
+                        VkCommandPool cmd_pool,
+                        uint32_t count,
+                        const VkCommandBuffer* cmdbufs) {
+    CommandPool& pool = *GetCommandPoolFromHandle(cmd_pool);
+    for (uint32_t i = 0; i < count; i++)
+        pool.allocator.pfnFree(pool.allocator.pUserData, cmdbufs[i]);
+}
+
+// -----------------------------------------------------------------------------
+// DeviceMemory
+
+struct DeviceMemory {
+    typedef VkDeviceMemory HandleType;
+    VkDeviceSize size;
+    alignas(16) uint8_t data[0];
+};
+DEFINE_OBJECT_HANDLE_CONVERSION(DeviceMemory)
+
+VkResult AllocateMemory(VkDevice device,
+                        const VkMemoryAllocateInfo* alloc_info,
+                        const VkAllocationCallbacks* allocator,
+                        VkDeviceMemory* mem_handle) {
+    if (SIZE_MAX - sizeof(DeviceMemory) <= alloc_info->allocationSize)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    if (!allocator)
+        allocator = &device->allocator;
+
+    size_t size = sizeof(DeviceMemory) + size_t(alloc_info->allocationSize);
+    DeviceMemory* mem = static_cast<DeviceMemory*>(allocator->pfnAllocation(
+        allocator->pUserData, size, alignof(DeviceMemory),
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+    if (!mem)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    mem->size = size;
+    *mem_handle = GetHandleToDeviceMemory(mem);
+    return VK_SUCCESS;
+}
+
+void FreeMemory(VkDevice device,
+                VkDeviceMemory mem_handle,
+                const VkAllocationCallbacks* allocator) {
+    if (!allocator)
+        allocator = &device->allocator;
+    DeviceMemory* mem = GetDeviceMemoryFromHandle(mem_handle);
+    allocator->pfnFree(allocator->pUserData, mem);
+}
+
+VkResult MapMemory(VkDevice,
+                   VkDeviceMemory mem_handle,
+                   VkDeviceSize offset,
+                   VkDeviceSize,
+                   VkMemoryMapFlags,
+                   void** out_ptr) {
+    DeviceMemory* mem = GetDeviceMemoryFromHandle(mem_handle);
+    *out_ptr = &mem->data[0] + offset;
+    return VK_SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
+// Buffer
+
+struct Buffer {
+    typedef VkBuffer HandleType;
+    VkDeviceSize size;
+};
+DEFINE_OBJECT_HANDLE_CONVERSION(Buffer)
+
+VkResult CreateBuffer(VkDevice device,
+                      const VkBufferCreateInfo* create_info,
+                      const VkAllocationCallbacks* allocator,
+                      VkBuffer* buffer_handle) {
+    ALOGW_IF(create_info->size > kMaxDeviceMemory,
+             "CreateBuffer: requested size 0x%" PRIx64
+             " exceeds max device memory size 0x%" PRIx64,
+             create_info->size, kMaxDeviceMemory);
+    if (!allocator)
+        allocator = &device->allocator;
+    Buffer* buffer = static_cast<Buffer*>(allocator->pfnAllocation(
+        allocator->pUserData, sizeof(Buffer), alignof(Buffer),
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+    if (!buffer)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    buffer->size = create_info->size;
+    *buffer_handle = GetHandleToBuffer(buffer);
+    return VK_SUCCESS;
+}
+
+void GetBufferMemoryRequirements(VkDevice,
+                                 VkBuffer buffer_handle,
+                                 VkMemoryRequirements* requirements) {
+    Buffer* buffer = GetBufferFromHandle(buffer_handle);
+    requirements->size = buffer->size;
+    requirements->alignment = 16;  // allow fast Neon/SSE memcpy
+    requirements->memoryTypeBits = 0x1;
+}
+
+void DestroyBuffer(VkDevice device,
+                   VkBuffer buffer_handle,
+                   const VkAllocationCallbacks* allocator) {
+    if (!allocator)
+        allocator = &device->allocator;
+    Buffer* buffer = GetBufferFromHandle(buffer_handle);
+    allocator->pfnFree(allocator->pUserData, buffer);
+}
+
+// -----------------------------------------------------------------------------
+// Image
+
+struct Image {
+    typedef VkImage HandleType;
+    VkDeviceSize size;
+};
+DEFINE_OBJECT_HANDLE_CONVERSION(Image)
+
+VkResult CreateImage(VkDevice device,
+                     const VkImageCreateInfo* create_info,
+                     const VkAllocationCallbacks* allocator,
+                     VkImage* image_handle) {
+    if (create_info->imageType != VK_IMAGE_TYPE_2D ||
+        create_info->format != VK_FORMAT_R8G8B8A8_UNORM ||
+        create_info->mipLevels != 1) {
+        ALOGE("CreateImage: not yet implemented: type=%d format=%d mips=%u",
+              create_info->imageType, create_info->format,
+              create_info->mipLevels);
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+
+    VkDeviceSize size =
+        VkDeviceSize(create_info->extent.width * create_info->extent.height) *
+        create_info->arrayLayers * create_info->samples * 4u;
+    ALOGW_IF(size > kMaxDeviceMemory,
+             "CreateImage: image size 0x%" PRIx64
+             " exceeds max device memory size 0x%" PRIx64,
+             size, kMaxDeviceMemory);
+
+    if (!allocator)
+        allocator = &device->allocator;
+    Image* image = static_cast<Image*>(allocator->pfnAllocation(
+        allocator->pUserData, sizeof(Image), alignof(Image),
+        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
+    if (!image)
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    image->size = size;
+    *image_handle = GetHandleToImage(image);
+    return VK_SUCCESS;
+}
+
+void GetImageMemoryRequirements(VkDevice,
+                                VkImage image_handle,
+                                VkMemoryRequirements* requirements) {
+    Image* image = GetImageFromHandle(image_handle);
+    requirements->size = image->size;
+    requirements->alignment = 16;  // allow fast Neon/SSE memcpy
+    requirements->memoryTypeBits = 0x1;
+}
+
+void DestroyImage(VkDevice device,
+                  VkImage image_handle,
+                  const VkAllocationCallbacks* allocator) {
+    if (!allocator)
+        allocator = &device->allocator;
+    Image* image = GetImageFromHandle(image_handle);
+    allocator->pfnFree(allocator->pUserData, image);
+}
+
+VkResult GetSwapchainGrallocUsageANDROID(VkDevice,
+                                         VkFormat,
+                                         VkImageUsageFlags,
+                                         int* grallocUsage) {
+    // The null driver never reads or writes the gralloc buffer
+    *grallocUsage = 0;
+    return VK_SUCCESS;
+}
+
+VkResult AcquireImageANDROID(VkDevice,
+                             VkImage,
+                             int fence,
+                             VkSemaphore,
+                             VkFence) {
+    close(fence);
+    return VK_SUCCESS;
+}
+
+VkResult QueueSignalReleaseImageANDROID(VkQueue,
+                                        uint32_t,
+                                        const VkSemaphore*,
+                                        VkImage,
+                                        int* fence) {
+    *fence = -1;
+    return VK_SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
+// No-op types
+
+VkResult CreateBufferView(VkDevice device,
+                          const VkBufferViewCreateInfo*,
+                          const VkAllocationCallbacks* /*allocator*/,
+                          VkBufferView* view) {
+    *view = AllocHandle<VkBufferView>(device, HandleType::kBufferView);
+    return VK_SUCCESS;
+}
+
+VkResult CreateDescriptorPool(VkDevice device,
+                              const VkDescriptorPoolCreateInfo*,
+                              const VkAllocationCallbacks* /*allocator*/,
+                              VkDescriptorPool* pool) {
+    *pool = AllocHandle<VkDescriptorPool>(device, HandleType::kDescriptorPool);
+    return VK_SUCCESS;
+}
+
+VkResult AllocateDescriptorSets(VkDevice device,
+                                const VkDescriptorSetAllocateInfo* alloc_info,
+                                VkDescriptorSet* descriptor_sets) {
+    for (uint32_t i = 0; i < alloc_info->descriptorSetCount; i++)
+        descriptor_sets[i] =
+            AllocHandle<VkDescriptorSet>(device, HandleType::kDescriptorSet);
+    return VK_SUCCESS;
+}
+
+VkResult CreateDescriptorSetLayout(VkDevice device,
+                                   const VkDescriptorSetLayoutCreateInfo*,
+                                   const VkAllocationCallbacks* /*allocator*/,
+                                   VkDescriptorSetLayout* layout) {
+    *layout = AllocHandle<VkDescriptorSetLayout>(
+        device, HandleType::kDescriptorSetLayout);
+    return VK_SUCCESS;
+}
+
+VkResult CreateEvent(VkDevice device,
+                     const VkEventCreateInfo*,
+                     const VkAllocationCallbacks* /*allocator*/,
+                     VkEvent* event) {
+    *event = AllocHandle<VkEvent>(device, HandleType::kEvent);
+    return VK_SUCCESS;
+}
+
+VkResult CreateFence(VkDevice device,
+                     const VkFenceCreateInfo*,
+                     const VkAllocationCallbacks* /*allocator*/,
+                     VkFence* fence) {
+    *fence = AllocHandle<VkFence>(device, HandleType::kFence);
+    return VK_SUCCESS;
+}
+
+VkResult CreateFramebuffer(VkDevice device,
+                           const VkFramebufferCreateInfo*,
+                           const VkAllocationCallbacks* /*allocator*/,
+                           VkFramebuffer* framebuffer) {
+    *framebuffer = AllocHandle<VkFramebuffer>(device, HandleType::kFramebuffer);
+    return VK_SUCCESS;
+}
+
+VkResult CreateImageView(VkDevice device,
+                         const VkImageViewCreateInfo*,
+                         const VkAllocationCallbacks* /*allocator*/,
+                         VkImageView* view) {
+    *view = AllocHandle<VkImageView>(device, HandleType::kImageView);
+    return VK_SUCCESS;
+}
+
+VkResult CreateGraphicsPipelines(VkDevice device,
+                                 VkPipelineCache,
+                                 uint32_t count,
+                                 const VkGraphicsPipelineCreateInfo*,
+                                 const VkAllocationCallbacks* /*allocator*/,
+                                 VkPipeline* pipelines) {
+    for (uint32_t i = 0; i < count; i++)
+        pipelines[i] = AllocHandle<VkPipeline>(device, HandleType::kPipeline);
+    return VK_SUCCESS;
+}
+
+VkResult CreateComputePipelines(VkDevice device,
+                                VkPipelineCache,
+                                uint32_t count,
+                                const VkComputePipelineCreateInfo*,
+                                const VkAllocationCallbacks* /*allocator*/,
+                                VkPipeline* pipelines) {
+    for (uint32_t i = 0; i < count; i++)
+        pipelines[i] = AllocHandle<VkPipeline>(device, HandleType::kPipeline);
+    return VK_SUCCESS;
+}
+
+VkResult CreatePipelineCache(VkDevice device,
+                             const VkPipelineCacheCreateInfo*,
+                             const VkAllocationCallbacks* /*allocator*/,
+                             VkPipelineCache* cache) {
+    *cache = AllocHandle<VkPipelineCache>(device, HandleType::kPipelineCache);
+    return VK_SUCCESS;
+}
+
+VkResult CreatePipelineLayout(VkDevice device,
+                              const VkPipelineLayoutCreateInfo*,
+                              const VkAllocationCallbacks* /*allocator*/,
+                              VkPipelineLayout* layout) {
+    *layout =
+        AllocHandle<VkPipelineLayout>(device, HandleType::kPipelineLayout);
+    return VK_SUCCESS;
+}
+
+VkResult CreateQueryPool(VkDevice device,
+                         const VkQueryPoolCreateInfo*,
+                         const VkAllocationCallbacks* /*allocator*/,
+                         VkQueryPool* pool) {
+    *pool = AllocHandle<VkQueryPool>(device, HandleType::kQueryPool);
+    return VK_SUCCESS;
+}
+
+VkResult CreateRenderPass(VkDevice device,
+                          const VkRenderPassCreateInfo*,
+                          const VkAllocationCallbacks* /*allocator*/,
+                          VkRenderPass* renderpass) {
+    *renderpass = AllocHandle<VkRenderPass>(device, HandleType::kRenderPass);
+    return VK_SUCCESS;
+}
+
+VkResult CreateSampler(VkDevice device,
+                       const VkSamplerCreateInfo*,
+                       const VkAllocationCallbacks* /*allocator*/,
+                       VkSampler* sampler) {
+    *sampler = AllocHandle<VkSampler>(device, HandleType::kSampler);
+    return VK_SUCCESS;
+}
+
+VkResult CreateSemaphore(VkDevice device,
+                         const VkSemaphoreCreateInfo*,
+                         const VkAllocationCallbacks* /*allocator*/,
+                         VkSemaphore* semaphore) {
+    *semaphore = AllocHandle<VkSemaphore>(device, HandleType::kSemaphore);
+    return VK_SUCCESS;
+}
+
+VkResult CreateShaderModule(VkDevice device,
+                            const VkShaderModuleCreateInfo*,
+                            const VkAllocationCallbacks* /*allocator*/,
+                            VkShaderModule* module) {
+    *module = AllocHandle<VkShaderModule>(device, HandleType::kShaderModule);
+    return VK_SUCCESS;
+}
+
+VkResult CreateDebugReportCallbackEXT(VkInstance instance,
+                                      const VkDebugReportCallbackCreateInfoEXT*,
+                                      const VkAllocationCallbacks*,
+                                      VkDebugReportCallbackEXT* callback) {
+    *callback = AllocHandle<VkDebugReportCallbackEXT>(
+        instance, HandleType::kDebugReportCallbackEXT);
+    return VK_SUCCESS;
+}
+
+// -----------------------------------------------------------------------------
+// No-op entrypoints
+
+// clang-format off
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-parameter"
+
+void GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult EnumerateInstanceLayerProperties(uint32_t* pCount, VkLayerProperties* pProperties) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmitInfo, VkFence fence) {
+    return VK_SUCCESS;
+}
+
+VkResult QueueWaitIdle(VkQueue queue) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult DeviceWaitIdle(VkDevice device) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void UnmapMemory(VkDevice device, VkDeviceMemory mem) {
+}
+
+VkResult FlushMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult InvalidateMappedMemoryRanges(VkDevice device, uint32_t memRangeCount, const VkMappedMemoryRange* pMemRanges) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+VkResult BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset) {
+    return VK_SUCCESS;
+}
+
+VkResult BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset) {
+    return VK_SUCCESS;
+}
+
+void GetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pNumRequirements, VkSparseImageMemoryRequirements* pSparseMemoryRequirements) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+void GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pNumProperties, VkSparseImageFormatProperties* pProperties) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+VkResult QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* allocator) {
+}
+
+VkResult ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences) {
+    return VK_SUCCESS;
+}
+
+VkResult GetFenceStatus(VkDevice device, VkFence fence) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout) {
+    return VK_SUCCESS;
+}
+
+void DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* allocator) {
+}
+
+VkResult GetEventStatus(VkDevice device, VkEvent event) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult SetEvent(VkDevice device, VkEvent event) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult ResetEvent(VkDevice device, VkEvent event) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* allocator) {
+}
+
+VkResult GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* allocator) {
+}
+
+void GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+void DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* allocator) {
+}
+
+VkResult GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult MergePipelineCaches(VkDevice device, VkPipelineCache destCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* allocator) {
+}
+
+VkResult ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void UpdateDescriptorSets(VkDevice device, uint32_t writeCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t copyCount, const VkCopyDescriptorSet* pDescriptorCopies) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+VkResult FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet* pDescriptorSets) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* allocator) {
+}
+
+void DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* allocator) {
+}
+
+void GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+}
+
+VkResult ResetCommandPool(VkDevice device, VkCommandPool cmdPool, VkCommandPoolResetFlags flags) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+VkResult BeginCommandBuffer(VkCommandBuffer cmdBuffer, const VkCommandBufferBeginInfo* pBeginInfo) {
+    return VK_SUCCESS;
+}
+
+VkResult EndCommandBuffer(VkCommandBuffer cmdBuffer) {
+    return VK_SUCCESS;
+}
+
+VkResult ResetCommandBuffer(VkCommandBuffer cmdBuffer, VkCommandBufferResetFlags flags) {
+    ALOGV("TODO: vk%s", __FUNCTION__);
+    return VK_SUCCESS;
+}
+
+void CmdBindPipeline(VkCommandBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+}
+
+void CmdSetViewport(VkCommandBuffer cmdBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports) {
+}
+
+void CmdSetScissor(VkCommandBuffer cmdBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors) {
+}
+
+void CmdSetLineWidth(VkCommandBuffer cmdBuffer, float lineWidth) {
+}
+
+void CmdSetDepthBias(VkCommandBuffer cmdBuffer, float depthBias, float depthBiasClamp, float slopeScaledDepthBias) {
+}
+
+void CmdSetBlendConstants(VkCommandBuffer cmdBuffer, const float blendConst[4]) {
+}
+
+void CmdSetDepthBounds(VkCommandBuffer cmdBuffer, float minDepthBounds, float maxDepthBounds) {
+}
+
+void CmdSetStencilCompareMask(VkCommandBuffer cmdBuffer, VkStencilFaceFlags faceMask, uint32_t stencilCompareMask) {
+}
+
+void CmdSetStencilWriteMask(VkCommandBuffer cmdBuffer, VkStencilFaceFlags faceMask, uint32_t stencilWriteMask) {
+}
+
+void CmdSetStencilReference(VkCommandBuffer cmdBuffer, VkStencilFaceFlags faceMask, uint32_t stencilReference) {
+}
+
+void CmdBindDescriptorSets(VkCommandBuffer cmdBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t setCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets) {
+}
+
+void CmdBindIndexBuffer(VkCommandBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+}
+
+void CmdBindVertexBuffers(VkCommandBuffer cmdBuffer, uint32_t startBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets) {
+}
+
+void CmdDraw(VkCommandBuffer cmdBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
+}
+
+void CmdDrawIndexed(VkCommandBuffer cmdBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
+}
+
+void CmdDrawIndirect(VkCommandBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+}
+
+void CmdDrawIndexedIndirect(VkCommandBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+}
+
+void CmdDispatch(VkCommandBuffer cmdBuffer, uint32_t x, uint32_t y, uint32_t z) {
+}
+
+void CmdDispatchIndirect(VkCommandBuffer cmdBuffer, VkBuffer buffer, VkDeviceSize offset) {
+}
+
+void CmdCopyBuffer(VkCommandBuffer cmdBuffer, VkBuffer srcBuffer, VkBuffer destBuffer, uint32_t regionCount, const VkBufferCopy* pRegions) {
+}
+
+void CmdCopyImage(VkCommandBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageCopy* pRegions) {
+}
+
+void CmdBlitImage(VkCommandBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter) {
+}
+
+void CmdCopyBufferToImage(VkCommandBuffer cmdBuffer, VkBuffer srcBuffer, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+}
+
+void CmdCopyImageToBuffer(VkCommandBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer destBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions) {
+}
+
+void CmdUpdateBuffer(VkCommandBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize dataSize, const uint32_t* pData) {
+}
+
+void CmdFillBuffer(VkCommandBuffer cmdBuffer, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize fillSize, uint32_t data) {
+}
+
+void CmdClearColorImage(VkCommandBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+}
+
+void CmdClearDepthStencilImage(VkCommandBuffer cmdBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges) {
+}
+
+void CmdClearAttachments(VkCommandBuffer cmdBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects) {
+}
+
+void CmdResolveImage(VkCommandBuffer cmdBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage destImage, VkImageLayout destImageLayout, uint32_t regionCount, const VkImageResolve* pRegions) {
+}
+
+void CmdSetEvent(VkCommandBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+}
+
+void CmdResetEvent(VkCommandBuffer cmdBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+}
+
+void CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
+}
+
+void CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers) {
+}
+
+void CmdBeginQuery(VkCommandBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
+}
+
+void CmdEndQuery(VkCommandBuffer cmdBuffer, VkQueryPool queryPool, uint32_t slot) {
+}
+
+void CmdResetQueryPool(VkCommandBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount) {
+}
+
+void CmdWriteTimestamp(VkCommandBuffer cmdBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t slot) {
+}
+
+void CmdCopyQueryPoolResults(VkCommandBuffer cmdBuffer, VkQueryPool queryPool, uint32_t startQuery, uint32_t queryCount, VkBuffer destBuffer, VkDeviceSize destOffset, VkDeviceSize destStride, VkQueryResultFlags flags) {
+}
+
+void CmdPushConstants(VkCommandBuffer cmdBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t start, uint32_t length, const void* values) {
+}
+
+void CmdBeginRenderPass(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents) {
+}
+
+void CmdNextSubpass(VkCommandBuffer cmdBuffer, VkSubpassContents contents) {
+}
+
+void CmdEndRenderPass(VkCommandBuffer cmdBuffer) {
+}
+
+void CmdExecuteCommands(VkCommandBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCommandBuffer* pCmdBuffers) {
+}
+
+void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator) {
+}
+
+void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage) {
+}
+
+#pragma clang diagnostic pop
+// clang-format on
+
+}  // namespace null_driver
diff --git a/vulkan/nulldrv/null_driver.tmpl b/vulkan/nulldrv/null_driver.tmpl
new file mode 100644
index 0000000..3a84971
--- /dev/null
+++ b/vulkan/nulldrv/null_driver.tmpl
@@ -0,0 +1,218 @@
+{{/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 "../api/templates/vulkan_common.tmpl"}}
+{{Global "clang-format" (Strings "clang-format" "-style=file")}}
+{{Macro "DefineGlobals" $}}
+{{$ | Macro "null_driver_gen.h"   | Format (Global "clang-format") | Write "null_driver_gen.h"  }}
+{{$ | Macro "null_driver_gen.cpp" | Format (Global "clang-format") | Write "null_driver_gen.cpp"}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  null_driver_gen.h
+-------------------------------------------------------------------------------
+*/}}
+{{define "null_driver_gen.h"}}
+/*
+•* Copyright 2015 The Android Open Source Project
+•*
+•* 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.
+•*/

+// WARNING: This file is generated. See ../README.md for instructions.

+#ifndef NULLDRV_NULL_DRIVER_H
+#define NULLDRV_NULL_DRIVER_H 1

+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>

+namespace null_driver {«

+PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name);

+// clang-format off
+  {{range $f := AllCommands $}}
+    {{if (Macro "IsDriverFunction" $f)}}
+VKAPI_ATTR {{Node "Type" $f.Return}} {{Macro "BaseName" $f}}({{Macro "Parameters" $f}});
+    {{end}}
+  {{end}}
+VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
+// clang-format on

+»}  // namespace null_driver

+#endif  // NULLDRV_NULL_DRIVER_H
+¶{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  null_driver_gen.cpp
+-------------------------------------------------------------------------------
+*/}}
+{{define "null_driver_gen.cpp"}}
+/*
+•* Copyright 2015 The Android Open Source Project
+•*
+•* 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.
+•*/

+// WARNING: This file is generated. See ../README.md for instructions.

+#include "null_driver_gen.h"
+#include <algorithm>

+using namespace null_driver;

+namespace {

+struct NameProc {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};

+PFN_vkVoidFunction Lookup(const char* name,
+                          const NameProc* begin,
+                          const NameProc* end) {
+    const auto& entry = std::lower_bound(
+        begin, end, name,
+        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry == end || strcmp(entry->name, name) != 0)
+        return nullptr;
+    return entry->proc;
+}

+template <size_t N>
+PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
+    return Lookup(name, procs, procs + N);
+}

+const NameProc kGlobalProcs[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if and (Macro "IsDriverFunction" $f) (eq (Macro "Vtbl" $f) "Global")}}
+      {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
+        static_cast<{{Macro "FunctionPtrName" $f}}>(§
+          {{Macro "BaseName" $f}}))},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+const NameProc kInstanceProcs[] = {«
+  // clang-format off
+  {{range $f := SortBy (AllCommands $) "FunctionName"}}
+    {{if (Macro "IsDriverFunction" $f)}}
+      {"{{$f.Name}}", reinterpret_cast<PFN_vkVoidFunction>(§
+        static_cast<{{Macro "FunctionPtrName" $f}}>(§
+          {{Macro "BaseName" $f}}))},
+    {{end}}
+  {{end}}
+  // clang-format on
+»};

+} // namespace

+namespace null_driver {

+PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
+    return Lookup(name, kGlobalProcs);
+}

+PFN_vkVoidFunction GetInstanceProcAddr(const char* name) {«
+    PFN_vkVoidFunction pfn;
+    if ((pfn = Lookup(name, kInstanceProcs)))
+        return pfn;
+    if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(GetSwapchainGrallocUsageANDROID));
+    if (strcmp(name, "vkAcquireImageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAcquireImageANDROID>(AcquireImageANDROID));
+    if (strcmp(name, "vkQueueSignalReleaseImageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueueSignalReleaseImageANDROID>(QueueSignalReleaseImageANDROID));
+    return nullptr;
+»}

+} // namespace null_driver

+{{end}}
+
+
+{{/*
+-------------------------------------------------------------------------------
+  Emits a function name without the "vk" prefix.
+-------------------------------------------------------------------------------
+*/}}
+{{define "BaseName"}}
+  {{AssertType $ "Function"}}
+  {{TrimPrefix "vk" $.Name}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Emits 'true' if the API function is implemented by the driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsDriverFunction"}}
+  {{AssertType $ "Function"}}
+
+  {{if not (GetAnnotation $ "pfn")}}
+    {{$ext := GetAnnotation $ "extension"}}
+    {{if $ext}}
+      {{Macro "IsDriverExtension" $ext}}
+    {{else}}
+      true
+    {{end}}
+  {{end}}
+{{end}}
+
+
+{{/*
+------------------------------------------------------------------------------
+  Reports whether an extension is implemented by the driver.
+------------------------------------------------------------------------------
+*/}}
+{{define "IsDriverExtension"}}
+  {{$ext := index $.Arguments 0}}
+  {{     if eq $ext "VK_ANDROID_native_buffer"}}true
+  {{else if eq $ext "VK_EXT_debug_report"}}true
+  {{end}}
+{{end}}
diff --git a/vulkan/nulldrv/null_driver_gen.cpp b/vulkan/nulldrv/null_driver_gen.cpp
new file mode 100644
index 0000000..10da993
--- /dev/null
+++ b/vulkan/nulldrv/null_driver_gen.cpp
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#include "null_driver_gen.h"
+#include <algorithm>
+
+using namespace null_driver;
+
+namespace {
+
+struct NameProc {
+    const char* name;
+    PFN_vkVoidFunction proc;
+};
+
+PFN_vkVoidFunction Lookup(const char* name,
+                          const NameProc* begin,
+                          const NameProc* end) {
+    const auto& entry = std::lower_bound(
+        begin, end, name,
+        [](const NameProc& e, const char* n) { return strcmp(e.name, n) < 0; });
+    if (entry == end || strcmp(entry->name, name) != 0)
+        return nullptr;
+    return entry->proc;
+}
+
+template <size_t N>
+PFN_vkVoidFunction Lookup(const char* name, const NameProc (&procs)[N]) {
+    return Lookup(name, procs, procs + N);
+}
+
+const NameProc kGlobalProcs[] = {
+    // clang-format off
+    {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance))},
+    {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties))},
+    {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties))},
+    // clang-format on
+};
+
+const NameProc kInstanceProcs[] = {
+    // clang-format off
+    {"vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateCommandBuffers>(AllocateCommandBuffers))},
+    {"vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateDescriptorSets>(AllocateDescriptorSets))},
+    {"vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkAllocateMemory>(AllocateMemory))},
+    {"vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBeginCommandBuffer>(BeginCommandBuffer))},
+    {"vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindBufferMemory>(BindBufferMemory))},
+    {"vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkBindImageMemory>(BindImageMemory))},
+    {"vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginQuery>(CmdBeginQuery))},
+    {"vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBeginRenderPass>(CmdBeginRenderPass))},
+    {"vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindDescriptorSets>(CmdBindDescriptorSets))},
+    {"vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindIndexBuffer>(CmdBindIndexBuffer))},
+    {"vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindPipeline>(CmdBindPipeline))},
+    {"vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBindVertexBuffers>(CmdBindVertexBuffers))},
+    {"vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdBlitImage>(CmdBlitImage))},
+    {"vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdClearAttachments>(CmdClearAttachments))},
+    {"vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdClearColorImage>(CmdClearColorImage))},
+    {"vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdClearDepthStencilImage>(CmdClearDepthStencilImage))},
+    {"vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyBuffer>(CmdCopyBuffer))},
+    {"vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyBufferToImage>(CmdCopyBufferToImage))},
+    {"vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyImage>(CmdCopyImage))},
+    {"vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyImageToBuffer>(CmdCopyImageToBuffer))},
+    {"vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdCopyQueryPoolResults>(CmdCopyQueryPoolResults))},
+    {"vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatch>(CmdDispatch))},
+    {"vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDispatchIndirect>(CmdDispatchIndirect))},
+    {"vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDraw>(CmdDraw))},
+    {"vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDrawIndexed>(CmdDrawIndexed))},
+    {"vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDrawIndexedIndirect>(CmdDrawIndexedIndirect))},
+    {"vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdDrawIndirect>(CmdDrawIndirect))},
+    {"vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdEndQuery>(CmdEndQuery))},
+    {"vkCmdEndRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdEndRenderPass>(CmdEndRenderPass))},
+    {"vkCmdExecuteCommands", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdExecuteCommands>(CmdExecuteCommands))},
+    {"vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdFillBuffer>(CmdFillBuffer))},
+    {"vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdNextSubpass>(CmdNextSubpass))},
+    {"vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPipelineBarrier>(CmdPipelineBarrier))},
+    {"vkCmdPushConstants", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdPushConstants>(CmdPushConstants))},
+    {"vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdResetEvent>(CmdResetEvent))},
+    {"vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdResetQueryPool>(CmdResetQueryPool))},
+    {"vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdResolveImage>(CmdResolveImage))},
+    {"vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetBlendConstants>(CmdSetBlendConstants))},
+    {"vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDepthBias>(CmdSetDepthBias))},
+    {"vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetDepthBounds>(CmdSetDepthBounds))},
+    {"vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetEvent>(CmdSetEvent))},
+    {"vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetLineWidth>(CmdSetLineWidth))},
+    {"vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetScissor>(CmdSetScissor))},
+    {"vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetStencilCompareMask>(CmdSetStencilCompareMask))},
+    {"vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetStencilReference>(CmdSetStencilReference))},
+    {"vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetStencilWriteMask>(CmdSetStencilWriteMask))},
+    {"vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdSetViewport>(CmdSetViewport))},
+    {"vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdUpdateBuffer>(CmdUpdateBuffer))},
+    {"vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdWaitEvents>(CmdWaitEvents))},
+    {"vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCmdWriteTimestamp>(CmdWriteTimestamp))},
+    {"vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateBuffer>(CreateBuffer))},
+    {"vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateBufferView>(CreateBufferView))},
+    {"vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateCommandPool>(CreateCommandPool))},
+    {"vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateComputePipelines>(CreateComputePipelines))},
+    {"vkCreateDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDebugReportCallbackEXT>(CreateDebugReportCallbackEXT))},
+    {"vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorPool>(CreateDescriptorPool))},
+    {"vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDescriptorSetLayout>(CreateDescriptorSetLayout))},
+    {"vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateDevice>(CreateDevice))},
+    {"vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateEvent>(CreateEvent))},
+    {"vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateFence>(CreateFence))},
+    {"vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateFramebuffer>(CreateFramebuffer))},
+    {"vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateGraphicsPipelines>(CreateGraphicsPipelines))},
+    {"vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateImage>(CreateImage))},
+    {"vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateImageView>(CreateImageView))},
+    {"vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateInstance>(CreateInstance))},
+    {"vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreatePipelineCache>(CreatePipelineCache))},
+    {"vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreatePipelineLayout>(CreatePipelineLayout))},
+    {"vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateQueryPool>(CreateQueryPool))},
+    {"vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateRenderPass>(CreateRenderPass))},
+    {"vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSampler>(CreateSampler))},
+    {"vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateSemaphore>(CreateSemaphore))},
+    {"vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkCreateShaderModule>(CreateShaderModule))},
+    {"vkDebugReportMessageEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDebugReportMessageEXT>(DebugReportMessageEXT))},
+    {"vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyBuffer>(DestroyBuffer))},
+    {"vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyBufferView>(DestroyBufferView))},
+    {"vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyCommandPool>(DestroyCommandPool))},
+    {"vkDestroyDebugReportCallbackEXT", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDebugReportCallbackEXT>(DestroyDebugReportCallbackEXT))},
+    {"vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorPool>(DestroyDescriptorPool))},
+    {"vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDescriptorSetLayout>(DestroyDescriptorSetLayout))},
+    {"vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyDevice>(DestroyDevice))},
+    {"vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyEvent>(DestroyEvent))},
+    {"vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyFence>(DestroyFence))},
+    {"vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyFramebuffer>(DestroyFramebuffer))},
+    {"vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyImage>(DestroyImage))},
+    {"vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyImageView>(DestroyImageView))},
+    {"vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyInstance>(DestroyInstance))},
+    {"vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyPipeline>(DestroyPipeline))},
+    {"vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyPipelineCache>(DestroyPipelineCache))},
+    {"vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyPipelineLayout>(DestroyPipelineLayout))},
+    {"vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyQueryPool>(DestroyQueryPool))},
+    {"vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyRenderPass>(DestroyRenderPass))},
+    {"vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySampler>(DestroySampler))},
+    {"vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroySemaphore>(DestroySemaphore))},
+    {"vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDestroyShaderModule>(DestroyShaderModule))},
+    {"vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkDeviceWaitIdle>(DeviceWaitIdle))},
+    {"vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEndCommandBuffer>(EndCommandBuffer))},
+    {"vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceExtensionProperties>(EnumerateDeviceExtensionProperties))},
+    {"vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateDeviceLayerProperties>(EnumerateDeviceLayerProperties))},
+    {"vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(EnumerateInstanceExtensionProperties))},
+    {"vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumerateInstanceLayerProperties>(EnumerateInstanceLayerProperties))},
+    {"vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkEnumeratePhysicalDevices>(EnumeratePhysicalDevices))},
+    {"vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFlushMappedMemoryRanges>(FlushMappedMemoryRanges))},
+    {"vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeCommandBuffers>(FreeCommandBuffers))},
+    {"vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeDescriptorSets>(FreeDescriptorSets))},
+    {"vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkFreeMemory>(FreeMemory))},
+    {"vkGetBufferMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetBufferMemoryRequirements>(GetBufferMemoryRequirements))},
+    {"vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceMemoryCommitment>(GetDeviceMemoryCommitment))},
+    {"vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceProcAddr>(GetDeviceProcAddr))},
+    {"vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetDeviceQueue>(GetDeviceQueue))},
+    {"vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetEventStatus>(GetEventStatus))},
+    {"vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetFenceStatus>(GetFenceStatus))},
+    {"vkGetImageMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageMemoryRequirements>(GetImageMemoryRequirements))},
+    {"vkGetImageSparseMemoryRequirements", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSparseMemoryRequirements>(GetImageSparseMemoryRequirements))},
+    {"vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetImageSubresourceLayout>(GetImageSubresourceLayout))},
+    {"vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetInstanceProcAddr>(GetInstanceProcAddr))},
+    {"vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFeatures>(GetPhysicalDeviceFeatures))},
+    {"vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceFormatProperties>(GetPhysicalDeviceFormatProperties))},
+    {"vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceImageFormatProperties>(GetPhysicalDeviceImageFormatProperties))},
+    {"vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceMemoryProperties>(GetPhysicalDeviceMemoryProperties))},
+    {"vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceProperties>(GetPhysicalDeviceProperties))},
+    {"vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceQueueFamilyProperties>(GetPhysicalDeviceQueueFamilyProperties))},
+    {"vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPhysicalDeviceSparseImageFormatProperties>(GetPhysicalDeviceSparseImageFormatProperties))},
+    {"vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetPipelineCacheData>(GetPipelineCacheData))},
+    {"vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetQueryPoolResults>(GetQueryPoolResults))},
+    {"vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkGetRenderAreaGranularity>(GetRenderAreaGranularity))},
+    {"vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkInvalidateMappedMemoryRanges>(InvalidateMappedMemoryRanges))},
+    {"vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkMapMemory>(MapMemory))},
+    {"vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkMergePipelineCaches>(MergePipelineCaches))},
+    {"vkQueueBindSparse", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueueBindSparse>(QueueBindSparse))},
+    {"vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueueSubmit>(QueueSubmit))},
+    {"vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkQueueWaitIdle>(QueueWaitIdle))},
+    {"vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetCommandBuffer>(ResetCommandBuffer))},
+    {"vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetCommandPool>(ResetCommandPool))},
+    {"vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetDescriptorPool>(ResetDescriptorPool))},
+    {"vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetEvent>(ResetEvent))},
+    {"vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkResetFences>(ResetFences))},
+    {"vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkSetEvent>(SetEvent))},
+    {"vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUnmapMemory>(UnmapMemory))},
+    {"vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkUpdateDescriptorSets>(UpdateDescriptorSets))},
+    {"vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(static_cast<PFN_vkWaitForFences>(WaitForFences))},
+    // clang-format on
+};
+
+}  // namespace
+
+namespace null_driver {
+
+PFN_vkVoidFunction GetGlobalProcAddr(const char* name) {
+    return Lookup(name, kGlobalProcs);
+}
+
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name) {
+    PFN_vkVoidFunction pfn;
+    if ((pfn = Lookup(name, kInstanceProcs)))
+        return pfn;
+    if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            static_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(
+                GetSwapchainGrallocUsageANDROID));
+    if (strcmp(name, "vkAcquireImageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            static_cast<PFN_vkAcquireImageANDROID>(AcquireImageANDROID));
+    if (strcmp(name, "vkQueueSignalReleaseImageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            static_cast<PFN_vkQueueSignalReleaseImageANDROID>(
+                QueueSignalReleaseImageANDROID));
+    return nullptr;
+}
+
+}  // namespace null_driver
diff --git a/vulkan/nulldrv/null_driver_gen.h b/vulkan/nulldrv/null_driver_gen.h
new file mode 100644
index 0000000..98952b8
--- /dev/null
+++ b/vulkan/nulldrv/null_driver_gen.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+// WARNING: This file is generated. See ../README.md for instructions.
+
+#ifndef NULLDRV_NULL_DRIVER_H
+#define NULLDRV_NULL_DRIVER_H 1
+
+#include <vulkan/vk_android_native_buffer.h>
+#include <vulkan/vulkan.h>
+
+namespace null_driver {
+
+PFN_vkVoidFunction GetGlobalProcAddr(const char* name);
+PFN_vkVoidFunction GetInstanceProcAddr(const char* name);
+
+// clang-format off
+VKAPI_ATTR VkResult CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance);
+VKAPI_ATTR void DestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult EnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount, VkPhysicalDevice* pPhysicalDevices);
+VKAPI_ATTR PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName);
+VKAPI_ATTR PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName);
+VKAPI_ATTR void GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties);
+VKAPI_ATTR void GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t* pQueueFamilyPropertyCount, VkQueueFamilyProperties* pQueueFamilyProperties);
+VKAPI_ATTR void GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+VKAPI_ATTR void GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures* pFeatures);
+VKAPI_ATTR void GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties* pFormatProperties);
+VKAPI_ATTR VkResult GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties);
+VKAPI_ATTR VkResult CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice);
+VKAPI_ATTR void DestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult EnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount, VkLayerProperties* pProperties);
+VKAPI_ATTR VkResult EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName, uint32_t* pPropertyCount, VkExtensionProperties* pProperties);
+VKAPI_ATTR void GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue);
+VKAPI_ATTR VkResult QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
+VKAPI_ATTR VkResult QueueWaitIdle(VkQueue queue);
+VKAPI_ATTR VkResult DeviceWaitIdle(VkDevice device);
+VKAPI_ATTR VkResult AllocateMemory(VkDevice device, const VkMemoryAllocateInfo* pAllocateInfo, const VkAllocationCallbacks* pAllocator, VkDeviceMemory* pMemory);
+VKAPI_ATTR void FreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult MapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void** ppData);
+VKAPI_ATTR void UnmapMemory(VkDevice device, VkDeviceMemory memory);
+VKAPI_ATTR VkResult FlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+VKAPI_ATTR VkResult InvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange* pMemoryRanges);
+VKAPI_ATTR void GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize* pCommittedMemoryInBytes);
+VKAPI_ATTR void GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements* pMemoryRequirements);
+VKAPI_ATTR VkResult BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+VKAPI_ATTR void GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements* pMemoryRequirements);
+VKAPI_ATTR VkResult BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset);
+VKAPI_ATTR void GetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t* pSparseMemoryRequirementCount, VkSparseImageMemoryRequirements* pSparseMemoryRequirements);
+VKAPI_ATTR void GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties);
+VKAPI_ATTR VkResult QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo* pBindInfo, VkFence fence);
+VKAPI_ATTR VkResult CreateFence(VkDevice device, const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFence* pFence);
+VKAPI_ATTR void DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult ResetFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences);
+VKAPI_ATTR VkResult GetFenceStatus(VkDevice device, VkFence fence);
+VKAPI_ATTR VkResult WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence* pFences, VkBool32 waitAll, uint64_t timeout);
+VKAPI_ATTR VkResult CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSemaphore* pSemaphore);
+VKAPI_ATTR void DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateEvent(VkDevice device, const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkEvent* pEvent);
+VKAPI_ATTR void DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult GetEventStatus(VkDevice device, VkEvent event);
+VKAPI_ATTR VkResult SetEvent(VkDevice device, VkEvent event);
+VKAPI_ATTR VkResult ResetEvent(VkDevice device, VkEvent event);
+VKAPI_ATTR VkResult CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkQueryPool* pQueryPool);
+VKAPI_ATTR void DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void* pData, VkDeviceSize stride, VkQueryResultFlags flags);
+VKAPI_ATTR VkResult CreateBuffer(VkDevice device, const VkBufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBuffer* pBuffer);
+VKAPI_ATTR void DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateBufferView(VkDevice device, const VkBufferViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkBufferView* pView);
+VKAPI_ATTR void DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage);
+VKAPI_ATTR void DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource* pSubresource, VkSubresourceLayout* pLayout);
+VKAPI_ATTR VkResult CreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView);
+VKAPI_ATTR void DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule);
+VKAPI_ATTR void DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache);
+VKAPI_ATTR void DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t* pDataSize, void* pData);
+VKAPI_ATTR VkResult MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
+VKAPI_ATTR VkResult CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkGraphicsPipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+VKAPI_ATTR VkResult CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo* pCreateInfos, const VkAllocationCallbacks* pAllocator, VkPipeline* pPipelines);
+VKAPI_ATTR void DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineLayout* pPipelineLayout);
+VKAPI_ATTR void DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateSampler(VkDevice device, const VkSamplerCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSampler* pSampler);
+VKAPI_ATTR void DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorSetLayout* pSetLayout);
+VKAPI_ATTR void DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDescriptorPool* pDescriptorPool);
+VKAPI_ATTR void DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags);
+VKAPI_ATTR VkResult AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo* pAllocateInfo, VkDescriptorSet* pDescriptorSets);
+VKAPI_ATTR VkResult FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets);
+VKAPI_ATTR void UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet* pDescriptorWrites, uint32_t descriptorCopyCount, const VkCopyDescriptorSet* pDescriptorCopies);
+VKAPI_ATTR VkResult CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkFramebuffer* pFramebuffer);
+VKAPI_ATTR void DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass);
+VKAPI_ATTR void DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D* pGranularity);
+VKAPI_ATTR VkResult CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkCommandPool* pCommandPool);
+VKAPI_ATTR void DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR VkResult ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags);
+VKAPI_ATTR VkResult AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo* pAllocateInfo, VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR void FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo* pBeginInfo);
+VKAPI_ATTR VkResult EndCommandBuffer(VkCommandBuffer commandBuffer);
+VKAPI_ATTR VkResult ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags);
+VKAPI_ATTR void CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+VKAPI_ATTR void CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport* pViewports);
+VKAPI_ATTR void CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D* pScissors);
+VKAPI_ATTR void CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth);
+VKAPI_ATTR void CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
+VKAPI_ATTR void CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]);
+VKAPI_ATTR void CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds);
+VKAPI_ATTR void CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask);
+VKAPI_ATTR void CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask);
+VKAPI_ATTR void CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference);
+VKAPI_ATTR void CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet* pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t* pDynamicOffsets);
+VKAPI_ATTR void CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType);
+VKAPI_ATTR void CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer* pBuffers, const VkDeviceSize* pOffsets);
+VKAPI_ATTR void CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance);
+VKAPI_ATTR void CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance);
+VKAPI_ATTR void CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+VKAPI_ATTR void CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t drawCount, uint32_t stride);
+VKAPI_ATTR void CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z);
+VKAPI_ATTR void CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset);
+VKAPI_ATTR void CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy* pRegions);
+VKAPI_ATTR void CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy* pRegions);
+VKAPI_ATTR void CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit* pRegions, VkFilter filter);
+VKAPI_ATTR void CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+VKAPI_ATTR void CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy* pRegions);
+VKAPI_ATTR void CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t* pData);
+VKAPI_ATTR void CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data);
+VKAPI_ATTR void CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearColorValue* pColor, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+VKAPI_ATTR void CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue* pDepthStencil, uint32_t rangeCount, const VkImageSubresourceRange* pRanges);
+VKAPI_ATTR void CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount, const VkClearAttachment* pAttachments, uint32_t rectCount, const VkClearRect* pRects);
+VKAPI_ATTR void CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve* pRegions);
+VKAPI_ATTR void CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+VKAPI_ATTR void CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask);
+VKAPI_ATTR void CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent* pEvents, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
+VKAPI_ATTR void CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier* pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier* pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier* pImageMemoryBarriers);
+VKAPI_ATTR void CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
+VKAPI_ATTR void CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t query);
+VKAPI_ATTR void CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+VKAPI_ATTR void CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t query);
+VKAPI_ATTR void CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags);
+VKAPI_ATTR void CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void* pValues);
+VKAPI_ATTR void CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin, VkSubpassContents contents);
+VKAPI_ATTR void CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
+VKAPI_ATTR void CmdEndRenderPass(VkCommandBuffer commandBuffer);
+VKAPI_ATTR void CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer* pCommandBuffers);
+VKAPI_ATTR VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback);
+VKAPI_ATTR void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator);
+VKAPI_ATTR void DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage);
+VKAPI_ATTR VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
+VKAPI_ATTR VkResult AcquireImageANDROID(VkDevice device, VkImage image, int nativeFenceFd, VkSemaphore semaphore, VkFence fence);
+VKAPI_ATTR VkResult QueueSignalReleaseImageANDROID(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int* pNativeFenceFd);
+// clang-format on
+
+}  // namespace null_driver
+
+#endif  // NULLDRV_NULL_DRIVER_H
diff --git a/vulkan/tools/Android.mk b/vulkan/tools/Android.mk
new file mode 100644
index 0000000..337e683
--- /dev/null
+++ b/vulkan/tools/Android.mk
@@ -0,0 +1,38 @@
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CLANG := true
+LOCAL_CFLAGS := -std=c99 -fvisibility=hidden -fstrict-aliasing
+LOCAL_CFLAGS += -DLOG_TAG=\"vkinfo\"
+LOCAL_CFLAGS += -Weverything -Werror -Wno-padded -Wno-undef -Wno-switch-enum
+LOCAL_CPPFLAGS := -std=c++1y \
+	-Wno-c++98-compat-pedantic \
+	-Wno-c99-extensions \
+	-Wno-old-style-cast
+
+LOCAL_C_INCLUDES := \
+	frameworks/native/vulkan/include
+
+LOCAL_SRC_FILES := vkinfo.cpp
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
+LOCAL_SHARED_LIBRARIES := libvulkan liblog
+
+LOCAL_MODULE := vkinfo
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_EXECUTABLE)
diff --git a/vulkan/tools/vkinfo.cpp b/vulkan/tools/vkinfo.cpp
new file mode 100644
index 0000000..62d8240
--- /dev/null
+++ b/vulkan/tools/vkinfo.cpp
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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 <algorithm>
+#include <array>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <sstream>
+#include <vector>
+
+#include <vulkan/vulkan.h>
+
+#define LOG_TAG "vkinfo"
+#include <log/log.h>
+
+namespace {
+
+struct Options {
+    bool layer_description;
+    bool layer_extensions;
+    bool unsupported_features;
+    bool validate;
+};
+
+struct GpuInfo {
+    VkPhysicalDeviceProperties properties;
+    VkPhysicalDeviceMemoryProperties memory;
+    VkPhysicalDeviceFeatures features;
+    std::vector<VkQueueFamilyProperties> queue_families;
+    std::vector<VkExtensionProperties> extensions;
+    std::vector<VkLayerProperties> layers;
+    std::vector<std::vector<VkExtensionProperties>> layer_extensions;
+};
+struct VulkanInfo {
+    std::vector<VkExtensionProperties> extensions;
+    std::vector<VkLayerProperties> layers;
+    std::vector<std::vector<VkExtensionProperties>> layer_extensions;
+    std::vector<GpuInfo> gpus;
+};
+
+// ----------------------------------------------------------------------------
+
+[[noreturn]] void die(const char* proc, VkResult result) {
+    const char* result_str;
+    switch (result) {
+        // clang-format off
+        case VK_SUCCESS: result_str = "VK_SUCCESS"; break;
+        case VK_NOT_READY: result_str = "VK_NOT_READY"; break;
+        case VK_TIMEOUT: result_str = "VK_TIMEOUT"; break;
+        case VK_EVENT_SET: result_str = "VK_EVENT_SET"; break;
+        case VK_EVENT_RESET: result_str = "VK_EVENT_RESET"; break;
+        case VK_INCOMPLETE: result_str = "VK_INCOMPLETE"; break;
+        case VK_ERROR_OUT_OF_HOST_MEMORY: result_str = "VK_ERROR_OUT_OF_HOST_MEMORY"; break;
+        case VK_ERROR_OUT_OF_DEVICE_MEMORY: result_str = "VK_ERROR_OUT_OF_DEVICE_MEMORY"; break;
+        case VK_ERROR_INITIALIZATION_FAILED: result_str = "VK_ERROR_INITIALIZATION_FAILED"; break;
+        case VK_ERROR_DEVICE_LOST: result_str = "VK_ERROR_DEVICE_LOST"; break;
+        case VK_ERROR_MEMORY_MAP_FAILED: result_str = "VK_ERROR_MEMORY_MAP_FAILED"; break;
+        case VK_ERROR_LAYER_NOT_PRESENT: result_str = "VK_ERROR_LAYER_NOT_PRESENT"; break;
+        case VK_ERROR_EXTENSION_NOT_PRESENT: result_str = "VK_ERROR_EXTENSION_NOT_PRESENT"; break;
+        case VK_ERROR_INCOMPATIBLE_DRIVER: result_str = "VK_ERROR_INCOMPATIBLE_DRIVER"; break;
+        default: result_str = "<unknown VkResult>"; break;
+            // clang-format on
+    }
+    fprintf(stderr, "%s failed: %s (%d)\n", proc, result_str, result);
+    exit(1);
+}
+
+bool HasExtension(const std::vector<VkExtensionProperties>& extensions,
+                  const char* name) {
+    return std::find_if(extensions.cbegin(), extensions.cend(),
+                        [=](const VkExtensionProperties& prop) {
+                            return strcmp(prop.extensionName, name) == 0;
+                        }) != extensions.end();
+}
+
+void EnumerateInstanceExtensions(
+    const char* layer_name,
+    std::vector<VkExtensionProperties>* extensions) {
+    VkResult result;
+    uint32_t count;
+    result =
+        vkEnumerateInstanceExtensionProperties(layer_name, &count, nullptr);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateInstanceExtensionProperties (count)", result);
+    do {
+        extensions->resize(count);
+        result = vkEnumerateInstanceExtensionProperties(layer_name, &count,
+                                                        extensions->data());
+    } while (result == VK_INCOMPLETE);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateInstanceExtensionProperties (data)", result);
+}
+
+void EnumerateDeviceExtensions(VkPhysicalDevice gpu,
+                               const char* layer_name,
+                               std::vector<VkExtensionProperties>* extensions) {
+    VkResult result;
+    uint32_t count;
+    result =
+        vkEnumerateDeviceExtensionProperties(gpu, layer_name, &count, nullptr);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateDeviceExtensionProperties (count)", result);
+    do {
+        extensions->resize(count);
+        result = vkEnumerateDeviceExtensionProperties(gpu, layer_name, &count,
+                                                      extensions->data());
+    } while (result == VK_INCOMPLETE);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateDeviceExtensionProperties (data)", result);
+}
+
+void GatherGpuInfo(VkPhysicalDevice gpu,
+                   const Options &options,
+                   GpuInfo& info) {
+    VkResult result;
+    uint32_t count;
+
+    vkGetPhysicalDeviceProperties(gpu, &info.properties);
+    vkGetPhysicalDeviceMemoryProperties(gpu, &info.memory);
+    vkGetPhysicalDeviceFeatures(gpu, &info.features);
+
+    vkGetPhysicalDeviceQueueFamilyProperties(gpu, &count, nullptr);
+    info.queue_families.resize(count);
+    vkGetPhysicalDeviceQueueFamilyProperties(gpu, &count,
+                                             info.queue_families.data());
+
+    result = vkEnumerateDeviceLayerProperties(gpu, &count, nullptr);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateDeviceLayerProperties (count)", result);
+    do {
+        info.layers.resize(count);
+        result =
+            vkEnumerateDeviceLayerProperties(gpu, &count, info.layers.data());
+    } while (result == VK_INCOMPLETE);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateDeviceLayerProperties (data)", result);
+    info.layer_extensions.resize(info.layers.size());
+
+    EnumerateDeviceExtensions(gpu, nullptr, &info.extensions);
+    for (size_t i = 0; i < info.layers.size(); i++) {
+        EnumerateDeviceExtensions(gpu, info.layers[i].layerName,
+                                  &info.layer_extensions[i]);
+    }
+
+    const std::array<const char*, 1> kDesiredExtensions = {
+        {VK_KHR_SWAPCHAIN_EXTENSION_NAME},
+    };
+    const char* extensions[kDesiredExtensions.size()];
+    uint32_t num_extensions = 0;
+    for (const auto& desired_ext : kDesiredExtensions) {
+        bool available = HasExtension(info.extensions, desired_ext);
+        if (options.validate) {
+            for (size_t i = 0; !available && i < info.layer_extensions.size();
+                 i++)
+                available = HasExtension(info.layer_extensions[i], desired_ext);
+        }
+        if (available)
+            extensions[num_extensions++] = desired_ext;
+    }
+
+    VkDevice device;
+    float queue_priorities[] = {0.0};
+    const VkDeviceQueueCreateInfo queue_create_info = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+        .queueFamilyIndex = 0,
+        .queueCount = 1,
+        queue_priorities
+    };
+    // clang-format off
+    const char *kValidationLayers[] = {
+        "VK_LAYER_GOOGLE_threading",
+        "VK_LAYER_LUNARG_parameter_validation",
+        "VK_LAYER_LUNARG_device_limits",
+        "VK_LAYER_LUNARG_object_tracker",
+        "VK_LAYER_LUNARG_image",
+        "VK_LAYER_LUNARG_core_validation",
+        "VK_LAYER_LUNARG_swapchain",
+        "VK_LAYER_GOOGLE_unique_objects"
+    };
+    // clang-format on
+    uint32_t num_layers = sizeof(kValidationLayers) / sizeof(char*);
+    const VkDeviceCreateInfo create_info = {
+        .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+        .queueCreateInfoCount = 1,
+        .pQueueCreateInfos = &queue_create_info,
+        .enabledExtensionCount = num_extensions,
+        .ppEnabledExtensionNames = extensions,
+        .enabledLayerCount = (options.validate) ? num_layers : 0,
+        .ppEnabledLayerNames = kValidationLayers,
+        .pEnabledFeatures = &info.features,
+    };
+    result = vkCreateDevice(gpu, &create_info, nullptr, &device);
+    if (result != VK_SUCCESS)
+        die("vkCreateDevice", result);
+    vkDestroyDevice(device, nullptr);
+}
+
+void GatherInfo(VulkanInfo* info, const Options& options) {
+    VkResult result;
+    uint32_t count;
+
+    result = vkEnumerateInstanceLayerProperties(&count, nullptr);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateInstanceLayerProperties (count)", result);
+    do {
+        info->layers.resize(count);
+        result =
+            vkEnumerateInstanceLayerProperties(&count, info->layers.data());
+    } while (result == VK_INCOMPLETE);
+    if (result != VK_SUCCESS)
+        die("vkEnumerateInstanceLayerProperties (data)", result);
+    info->layer_extensions.resize(info->layers.size());
+
+    EnumerateInstanceExtensions(nullptr, &info->extensions);
+    for (size_t i = 0; i < info->layers.size(); i++) {
+        EnumerateInstanceExtensions(info->layers[i].layerName,
+                                    &info->layer_extensions[i]);
+    }
+
+    const char* kDesiredExtensions[] = {
+        VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
+    };
+    const char*
+        extensions[sizeof(kDesiredExtensions) / sizeof(kDesiredExtensions[0])];
+    uint32_t num_extensions = 0;
+    for (const auto& desired_ext : kDesiredExtensions) {
+        bool available = HasExtension(info->extensions, desired_ext);
+        if (options.validate) {
+            for (size_t i = 0; !available && i < info->layer_extensions.size();
+                 i++)
+                available =
+                    HasExtension(info->layer_extensions[i], desired_ext);
+        }
+        if (available)
+            extensions[num_extensions++] = desired_ext;
+    }
+
+    // clang-format off
+    const char *kValidationLayers[] = {
+        "VK_LAYER_GOOGLE_threading",
+        "VK_LAYER_LUNARG_parameter_validation",
+        "VK_LAYER_LUNARG_device_limits",
+        "VK_LAYER_LUNARG_object_tracker",
+        "VK_LAYER_LUNARG_image",
+        "VK_LAYER_LUNARG_core_validation",
+        "VK_LAYER_LUNARG_swapchain",
+        "VK_LAYER_GOOGLE_unique_objects"
+    };
+    // clang-format on
+    uint32_t num_layers = sizeof(kValidationLayers) / sizeof(char*);
+
+    const VkApplicationInfo application_info = {
+        .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+        .pApplicationName = "vkinfo",
+        .applicationVersion = 0,
+        .pEngineName = "vkinfo",
+        .engineVersion = 0,
+        .apiVersion = VK_API_VERSION,
+    };
+    const VkInstanceCreateInfo create_info = {
+        .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+        .pApplicationInfo = &application_info,
+        .enabledExtensionCount = num_extensions,
+        .ppEnabledExtensionNames = extensions,
+        .enabledLayerCount = (options.validate) ? num_layers : 0,
+        .ppEnabledLayerNames = kValidationLayers,
+    };
+    VkInstance instance;
+    result = vkCreateInstance(&create_info, nullptr, &instance);
+    if (result != VK_SUCCESS)
+        die("vkCreateInstance", result);
+
+    uint32_t num_gpus;
+    result = vkEnumeratePhysicalDevices(instance, &num_gpus, nullptr);
+    if (result != VK_SUCCESS)
+        die("vkEnumeratePhysicalDevices (count)", result);
+    std::vector<VkPhysicalDevice> gpus(num_gpus, VK_NULL_HANDLE);
+    do {
+        gpus.resize(num_gpus, VK_NULL_HANDLE);
+        result = vkEnumeratePhysicalDevices(instance, &num_gpus, gpus.data());
+    } while (result == VK_INCOMPLETE);
+    if (result != VK_SUCCESS)
+        die("vkEnumeratePhysicalDevices (data)", result);
+
+    info->gpus.resize(num_gpus);
+    for (size_t i = 0; i < gpus.size(); i++)
+        GatherGpuInfo(gpus[i], options, info->gpus.at(i));
+
+    vkDestroyInstance(instance, nullptr);
+}
+
+// ----------------------------------------------------------------------------
+
+const size_t kMaxIndent = 8;
+const size_t kIndentSize = 3;
+std::array<char, kMaxIndent * kIndentSize + 1> kIndent;
+const char* Indent(size_t n) {
+    static bool initialized = false;
+    if (!initialized) {
+        kIndent.fill(' ');
+        kIndent.back() = '\0';
+        initialized = true;
+    }
+    return kIndent.data() +
+           (kIndent.size() - (kIndentSize * std::min(n, kMaxIndent) + 1));
+}
+
+const char* VkPhysicalDeviceTypeStr(VkPhysicalDeviceType type) {
+    switch (type) {
+        case VK_PHYSICAL_DEVICE_TYPE_OTHER:
+            return "OTHER";
+        case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
+            return "INTEGRATED_GPU";
+        case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
+            return "DISCRETE_GPU";
+        case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU:
+            return "VIRTUAL_GPU";
+        case VK_PHYSICAL_DEVICE_TYPE_CPU:
+            return "CPU";
+        default:
+            return "<UNKNOWN>";
+    }
+}
+
+void PrintExtensions(const std::vector<VkExtensionProperties>& extensions,
+                     const Options& /*options*/,
+                     size_t indent) {
+    for (const auto& e : extensions)
+        printf("%s%s (v%u)\n", Indent(indent), e.extensionName, e.specVersion);
+}
+
+void PrintLayers(
+    const std::vector<VkLayerProperties>& layers,
+    const std::vector<std::vector<VkExtensionProperties>> extensions,
+    const Options& options,
+    size_t indent) {
+    for (size_t i = 0; i < layers.size(); i++) {
+        printf("%s%s %u.%u.%u/%u\n", Indent(indent), layers[i].layerName,
+               VK_VERSION_MAJOR(layers[i].specVersion),
+               VK_VERSION_MINOR(layers[i].specVersion),
+               VK_VERSION_PATCH(layers[i].specVersion),
+               layers[i].implementationVersion);
+        if (options.layer_description)
+            printf("%s%s\n", Indent(indent + 1), layers[i].description);
+        if (options.layer_extensions && !extensions[i].empty()) {
+            if (!extensions[i].empty()) {
+                printf("%sExtensions [%zu]:\n", Indent(indent + 1),
+                       extensions[i].size());
+                PrintExtensions(extensions[i], options, indent + 2);
+            }
+        }
+    }
+}
+
+void PrintAllFeatures(const char* indent,
+                      const VkPhysicalDeviceFeatures& features) {
+    // clang-format off
+    printf("%srobustBufferAccess: %s\n", indent, features.robustBufferAccess ? "YES" : "NO");
+    printf("%sfullDrawIndexUint32: %s\n", indent, features.fullDrawIndexUint32 ? "YES" : "NO");
+    printf("%simageCubeArray: %s\n", indent, features.imageCubeArray ? "YES" : "NO");
+    printf("%sindependentBlend: %s\n", indent, features.independentBlend ? "YES" : "NO");
+    printf("%sgeometryShader: %s\n", indent, features.geometryShader ? "YES" : "NO");
+    printf("%stessellationShader: %s\n", indent, features.tessellationShader ? "YES" : "NO");
+    printf("%ssampleRateShading: %s\n", indent, features.sampleRateShading ? "YES" : "NO");
+    printf("%sdualSrcBlend: %s\n", indent, features.dualSrcBlend ? "YES" : "NO");
+    printf("%slogicOp: %s\n", indent, features.logicOp ? "YES" : "NO");
+    printf("%smultiDrawIndirect: %s\n", indent, features.multiDrawIndirect ? "YES" : "NO");
+    printf("%sdrawIndirectFirstInstance: %s\n", indent, features.drawIndirectFirstInstance ? "YES" : "NO");
+    printf("%sdepthClamp: %s\n", indent, features.depthClamp ? "YES" : "NO");
+    printf("%sdepthBiasClamp: %s\n", indent, features.depthBiasClamp ? "YES" : "NO");
+    printf("%sfillModeNonSolid: %s\n", indent, features.fillModeNonSolid ? "YES" : "NO");
+    printf("%sdepthBounds: %s\n", indent, features.depthBounds ? "YES" : "NO");
+    printf("%swideLines: %s\n", indent, features.wideLines ? "YES" : "NO");
+    printf("%slargePoints: %s\n", indent, features.largePoints ? "YES" : "NO");
+    printf("%salphaToOne: %s\n", indent, features.alphaToOne ? "YES" : "NO");
+    printf("%smultiViewport: %s\n", indent, features.multiViewport ? "YES" : "NO");
+    printf("%ssamplerAnisotropy: %s\n", indent, features.samplerAnisotropy ? "YES" : "NO");
+    printf("%stextureCompressionETC2: %s\n", indent, features.textureCompressionETC2 ? "YES" : "NO");
+    printf("%stextureCompressionASTC_LDR: %s\n", indent, features.textureCompressionASTC_LDR ? "YES" : "NO");
+    printf("%stextureCompressionBC: %s\n", indent, features.textureCompressionBC ? "YES" : "NO");
+    printf("%socclusionQueryPrecise: %s\n", indent, features.occlusionQueryPrecise ? "YES" : "NO");
+    printf("%spipelineStatisticsQuery: %s\n", indent, features.pipelineStatisticsQuery ? "YES" : "NO");
+    printf("%svertexPipelineStoresAndAtomics: %s\n", indent, features.vertexPipelineStoresAndAtomics ? "YES" : "NO");
+    printf("%sfragmentStoresAndAtomics: %s\n", indent, features.fragmentStoresAndAtomics ? "YES" : "NO");
+    printf("%sshaderTessellationAndGeometryPointSize: %s\n", indent, features.shaderTessellationAndGeometryPointSize ? "YES" : "NO");
+    printf("%sshaderImageGatherExtended: %s\n", indent, features.shaderImageGatherExtended ? "YES" : "NO");
+    printf("%sshaderStorageImageExtendedFormats: %s\n", indent, features.shaderStorageImageExtendedFormats ? "YES" : "NO");
+    printf("%sshaderStorageImageMultisample: %s\n", indent, features.shaderStorageImageMultisample ? "YES" : "NO");
+    printf("%sshaderStorageImageReadWithoutFormat: %s\n", indent, features.shaderStorageImageReadWithoutFormat ? "YES" : "NO");
+    printf("%sshaderStorageImageWriteWithoutFormat: %s\n", indent, features.shaderStorageImageWriteWithoutFormat ? "YES" : "NO");
+    printf("%sshaderUniformBufferArrayDynamicIndexing: %s\n", indent, features.shaderUniformBufferArrayDynamicIndexing ? "YES" : "NO");
+    printf("%sshaderSampledImageArrayDynamicIndexing: %s\n", indent, features.shaderSampledImageArrayDynamicIndexing ? "YES" : "NO");
+    printf("%sshaderStorageBufferArrayDynamicIndexing: %s\n", indent, features.shaderStorageBufferArrayDynamicIndexing ? "YES" : "NO");
+    printf("%sshaderStorageImageArrayDynamicIndexing: %s\n", indent, features.shaderStorageImageArrayDynamicIndexing ? "YES" : "NO");
+    printf("%sshaderClipDistance: %s\n", indent, features.shaderClipDistance ? "YES" : "NO");
+    printf("%sshaderCullDistance: %s\n", indent, features.shaderCullDistance ? "YES" : "NO");
+    printf("%sshaderFloat64: %s\n", indent, features.shaderFloat64 ? "YES" : "NO");
+    printf("%sshaderInt64: %s\n", indent, features.shaderInt64 ? "YES" : "NO");
+    printf("%sshaderInt16: %s\n", indent, features.shaderInt16 ? "YES" : "NO");
+    printf("%sshaderResourceResidency: %s\n", indent, features.shaderResourceResidency ? "YES" : "NO");
+    printf("%sshaderResourceMinLod: %s\n", indent, features.shaderResourceMinLod ? "YES" : "NO");
+    printf("%ssparseBinding: %s\n", indent, features.sparseBinding ? "YES" : "NO");
+    printf("%ssparseResidencyBuffer: %s\n", indent, features.sparseResidencyBuffer ? "YES" : "NO");
+    printf("%ssparseResidencyImage2D: %s\n", indent, features.sparseResidencyImage2D ? "YES" : "NO");
+    printf("%ssparseResidencyImage3D: %s\n", indent, features.sparseResidencyImage3D ? "YES" : "NO");
+    printf("%ssparseResidency2Samples: %s\n", indent, features.sparseResidency2Samples ? "YES" : "NO");
+    printf("%ssparseResidency4Samples: %s\n", indent, features.sparseResidency4Samples ? "YES" : "NO");
+    printf("%ssparseResidency8Samples: %s\n", indent, features.sparseResidency8Samples ? "YES" : "NO");
+    printf("%ssparseResidency16Samples: %s\n", indent, features.sparseResidency16Samples ? "YES" : "NO");
+    printf("%ssparseResidencyAliased: %s\n", indent, features.sparseResidencyAliased ? "YES" : "NO");
+    printf("%svariableMultisampleRate: %s\n", indent, features.variableMultisampleRate ? "YES" : "NO");
+    printf("%sinheritedQueries: %s\n", indent, features.inheritedQueries ? "YES" : "NO");
+    // clang-format on
+}
+
+void PrintSupportedFeatures(const char* indent,
+                            const VkPhysicalDeviceFeatures& features) {
+    // clang-format off
+    if (features.robustBufferAccess) printf("%srobustBufferAccess\n", indent);
+    if (features.fullDrawIndexUint32) printf("%sfullDrawIndexUint32\n", indent);
+    if (features.imageCubeArray) printf("%simageCubeArray\n", indent);
+    if (features.independentBlend) printf("%sindependentBlend\n", indent);
+    if (features.geometryShader) printf("%sgeometryShader\n", indent);
+    if (features.tessellationShader) printf("%stessellationShader\n", indent);
+    if (features.sampleRateShading) printf("%ssampleRateShading\n", indent);
+    if (features.dualSrcBlend) printf("%sdualSrcBlend\n", indent);
+    if (features.logicOp) printf("%slogicOp\n", indent);
+    if (features.multiDrawIndirect) printf("%smultiDrawIndirect\n", indent);
+    if (features.drawIndirectFirstInstance) printf("%sdrawIndirectFirstInstance\n", indent);
+    if (features.depthClamp) printf("%sdepthClamp\n", indent);
+    if (features.depthBiasClamp) printf("%sdepthBiasClamp\n", indent);
+    if (features.fillModeNonSolid) printf("%sfillModeNonSolid\n", indent);
+    if (features.depthBounds) printf("%sdepthBounds\n", indent);
+    if (features.wideLines) printf("%swideLines\n", indent);
+    if (features.largePoints) printf("%slargePoints\n", indent);
+    if (features.alphaToOne) printf("%salphaToOne\n", indent);
+    if (features.multiViewport) printf("%smultiViewport\n", indent);
+    if (features.samplerAnisotropy) printf("%ssamplerAnisotropy\n", indent);
+    if (features.textureCompressionETC2) printf("%stextureCompressionETC2\n", indent);
+    if (features.textureCompressionASTC_LDR) printf("%stextureCompressionASTC_LDR\n", indent);
+    if (features.textureCompressionBC) printf("%stextureCompressionBC\n", indent);
+    if (features.occlusionQueryPrecise) printf("%socclusionQueryPrecise\n", indent);
+    if (features.pipelineStatisticsQuery) printf("%spipelineStatisticsQuery\n", indent);
+    if (features.vertexPipelineStoresAndAtomics) printf("%svertexPipelineStoresAndAtomics\n", indent);
+    if (features.fragmentStoresAndAtomics) printf("%sfragmentStoresAndAtomics\n", indent);
+    if (features.shaderTessellationAndGeometryPointSize) printf("%sshaderTessellationAndGeometryPointSize\n", indent);
+    if (features.shaderImageGatherExtended) printf("%sshaderImageGatherExtended\n", indent);
+    if (features.shaderStorageImageExtendedFormats) printf("%sshaderStorageImageExtendedFormats\n", indent);
+    if (features.shaderStorageImageMultisample) printf("%sshaderStorageImageMultisample\n", indent);
+    if (features.shaderStorageImageReadWithoutFormat) printf("%sshaderStorageImageReadWithoutFormat\n", indent);
+    if (features.shaderStorageImageWriteWithoutFormat) printf("%sshaderStorageImageWriteWithoutFormat\n", indent);
+    if (features.shaderUniformBufferArrayDynamicIndexing) printf("%sshaderUniformBufferArrayDynamicIndexing\n", indent);
+    if (features.shaderSampledImageArrayDynamicIndexing) printf("%sshaderSampledImageArrayDynamicIndexing\n", indent);
+    if (features.shaderStorageBufferArrayDynamicIndexing) printf("%sshaderStorageBufferArrayDynamicIndexing\n", indent);
+    if (features.shaderStorageImageArrayDynamicIndexing) printf("%sshaderStorageImageArrayDynamicIndexing\n", indent);
+    if (features.shaderClipDistance) printf("%sshaderClipDistance\n", indent);
+    if (features.shaderCullDistance) printf("%sshaderCullDistance\n", indent);
+    if (features.shaderFloat64) printf("%sshaderFloat64\n", indent);
+    if (features.shaderInt64) printf("%sshaderInt64\n", indent);
+    if (features.shaderInt16) printf("%sshaderInt16\n", indent);
+    if (features.shaderResourceResidency) printf("%sshaderResourceResidency\n", indent);
+    if (features.shaderResourceMinLod) printf("%sshaderResourceMinLod\n", indent);
+    if (features.sparseBinding) printf("%ssparseBinding\n", indent);
+    if (features.sparseResidencyBuffer) printf("%ssparseResidencyBuffer\n", indent);
+    if (features.sparseResidencyImage2D) printf("%ssparseResidencyImage2D\n", indent);
+    if (features.sparseResidencyImage3D) printf("%ssparseResidencyImage3D\n", indent);
+    if (features.sparseResidency2Samples) printf("%ssparseResidency2Samples\n", indent);
+    if (features.sparseResidency4Samples) printf("%ssparseResidency4Samples\n", indent);
+    if (features.sparseResidency8Samples) printf("%ssparseResidency8Samples\n", indent);
+    if (features.sparseResidency16Samples) printf("%ssparseResidency16Samples\n", indent);
+    if (features.sparseResidencyAliased) printf("%ssparseResidencyAliased\n", indent);
+    if (features.variableMultisampleRate) printf("%svariableMultisampleRate\n", indent);
+    if (features.inheritedQueries) printf("%sinheritedQueries\n", indent);
+    // clang-format on
+}
+
+void PrintGpuInfo(const GpuInfo& info, const Options& options, size_t indent) {
+    VkResult result;
+    std::ostringstream strbuf;
+
+    printf("%s\"%s\" (%s) %u.%u.%u/%#x [%04x:%04x]\n", Indent(indent),
+           info.properties.deviceName,
+           VkPhysicalDeviceTypeStr(info.properties.deviceType),
+           VK_VERSION_MAJOR(info.properties.apiVersion),
+           VK_VERSION_MINOR(info.properties.apiVersion),
+           VK_VERSION_PATCH(info.properties.apiVersion),
+           info.properties.driverVersion, info.properties.vendorID,
+           info.properties.deviceID);
+
+    for (uint32_t heap = 0; heap < info.memory.memoryHeapCount; heap++) {
+        if ((info.memory.memoryHeaps[heap].flags &
+             VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) != 0)
+            strbuf << "DEVICE_LOCAL";
+        printf("%sHeap %u: %" PRIu64 " MiB (0x%" PRIx64 " B) %s\n",
+               Indent(indent + 1), heap,
+               info.memory.memoryHeaps[heap].size / 0x100000,
+               info.memory.memoryHeaps[heap].size, strbuf.str().c_str());
+        strbuf.str(std::string());
+
+        for (uint32_t type = 0; type < info.memory.memoryTypeCount; type++) {
+            if (info.memory.memoryTypes[type].heapIndex != heap)
+                continue;
+            VkMemoryPropertyFlags flags =
+                info.memory.memoryTypes[type].propertyFlags;
+            if ((flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) != 0)
+                strbuf << " DEVICE_LOCAL";
+            if ((flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) != 0)
+                strbuf << " HOST_VISIBLE";
+            if ((flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0)
+                strbuf << " COHERENT";
+            if ((flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) != 0)
+                strbuf << " CACHED";
+            if ((flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) != 0)
+                strbuf << " LAZILY_ALLOCATED";
+            printf("%sType %u:%s\n", Indent(indent + 2), type,
+                   strbuf.str().c_str());
+            strbuf.str(std::string());
+        }
+    }
+
+    for (uint32_t family = 0; family < info.queue_families.size(); family++) {
+        const VkQueueFamilyProperties& qprops = info.queue_families[family];
+        VkQueueFlags flags = qprops.queueFlags;
+        char flags_str[5];
+        flags_str[0] = (flags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '_';
+        flags_str[1] = (flags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '_';
+        flags_str[2] = (flags & VK_QUEUE_TRANSFER_BIT) ? 'T' : '_';
+        flags_str[3] = (flags & VK_QUEUE_SPARSE_BINDING_BIT) ? 'S' : '_';
+        flags_str[4] = '\0';
+        printf(
+            "%sQueue Family %u: %ux %s\n"
+            "%stimestampValidBits: %ub\n"
+            "%sminImageTransferGranularity: (%u,%u,%u)\n",
+            Indent(indent + 1), family, qprops.queueCount, flags_str,
+            Indent(indent + 2), qprops.timestampValidBits, Indent(indent + 2),
+            qprops.minImageTransferGranularity.width,
+            qprops.minImageTransferGranularity.height,
+            qprops.minImageTransferGranularity.depth);
+    }
+
+    printf("%sFeatures:\n", Indent(indent + 1));
+    if (options.unsupported_features) {
+        PrintAllFeatures(Indent(indent + 2), info.features);
+    } else {
+        PrintSupportedFeatures(Indent(indent + 2), info.features);
+    }
+
+    printf("%sExtensions [%zu]:\n", Indent(indent + 1), info.extensions.size());
+    if (!info.extensions.empty())
+        PrintExtensions(info.extensions, options, indent + 2);
+    printf("%sLayers [%zu]:\n", Indent(indent + 1), info.layers.size());
+    if (!info.layers.empty())
+        PrintLayers(info.layers, info.layer_extensions, options, indent + 2);
+}
+
+void PrintInfo(const VulkanInfo& info, const Options& options) {
+    std::ostringstream strbuf;
+    size_t indent = 0;
+
+    printf("%sInstance Extensions [%zu]:\n", Indent(indent),
+           info.extensions.size());
+    PrintExtensions(info.extensions, options, indent + 1);
+    printf("%sInstance Layers [%zu]:\n", Indent(indent), info.layers.size());
+    if (!info.layers.empty())
+        PrintLayers(info.layers, info.layer_extensions, options, indent + 1);
+
+    printf("%sPhysicalDevices [%zu]:\n", Indent(indent), info.gpus.size());
+    for (const auto& gpu : info.gpus)
+        PrintGpuInfo(gpu, options, indent + 1);
+}
+
+const char kUsageString[] =
+    "usage: vkinfo [options]\n"
+    "  -v                       enable all the following verbose options\n"
+    "    -layer_description     print layer description strings\n"
+    "    -layer_extensions      print extensions supported by each layer\n"
+    "    -unsupported_features  print all physical device features\n"
+    "  -validate                enable validation layers if present\n"
+    "  -debug_pause             pause at start until resumed via debugger\n";
+
+}  // namespace
+
+// ----------------------------------------------------------------------------
+
+int main(int argc, char const* argv[]) {
+    static volatile bool startup_pause = false;
+    Options options = {
+        .layer_description = false, .layer_extensions = false,
+        .unsupported_features = false,
+        .validate = false,
+    };
+    for (int argi = 1; argi < argc; argi++) {
+        if (strcmp(argv[argi], "-h") == 0) {
+            fputs(kUsageString, stdout);
+            return 0;
+        }
+        if (strcmp(argv[argi], "-v") == 0) {
+            options.layer_description = true;
+            options.layer_extensions = true;
+            options.unsupported_features = true;
+        } else if (strcmp(argv[argi], "-layer_description") == 0) {
+            options.layer_description = true;
+        } else if (strcmp(argv[argi], "-layer_extensions") == 0) {
+            options.layer_extensions = true;
+        } else if (strcmp(argv[argi], "-unsupported_features") == 0) {
+            options.unsupported_features = true;
+        } else if (strcmp(argv[argi], "-validate") == 0) {
+            options.validate = true;
+        } else if (strcmp(argv[argi], "-debug_pause") == 0) {
+            startup_pause = true;
+        }
+    }
+
+    while (startup_pause) {
+        sleep(0);
+    }
+
+    VulkanInfo info;
+    GatherInfo(&info, options);
+    PrintInfo(info, options);
+    return 0;
+}